为什么行尾 $ 锚点不能与 grep 命令一起使用,尽管行首 ^ 锚点可以使用?

为什么行尾 $ 锚点不能与 grep 命令一起使用,尽管行首 ^ 锚点可以使用?

对于 UNIX 来说非常陌生,但对于编程来说并不陌生。在 MacBook 上使用终端。为了管理和搜索填字游戏构建的单词列表,我尝试使用 Grep 命令及其变体。看起来很简单,但很早就被我认为应该是一个简单的案例所困扰。

当我进入

grep "^COW" masternospaces.txt

我得到了我想要的:以 COW 开头的所有单词的列表。

但是当我进入

grep "COW$" masternospaces.txt

我期望得到一个以 COW 结尾的单词列表(有很多这样的单词),但什么也没有返回。

该文件是纯文本文件,每行只是一个全部大写的单词(或没有空格的单词短语)。

知道这里会发生什么吗?

答案1

正如 @steeldriver 提到的,问题可能是由与grep预期不同的行结束样式引起的。

检查行结尾

您可以使用它hexdump来准确检查行结尾的格式。我建议你使用我最喜欢的格式:

hexdump -e '"%08_ad (0x%08_ax)    "8/1 "%02x ""   "8/1 "%02x "' -e '"    "8/1 "%_p""|"8/1 "%_p""\n"' masternospaces.txt

在输出中,检查行结尾:0a-> LF, 0d-> CR。一个非常简单的例子是这样的:

$ hexdump -e '"%08_ad (0x%08_ax)    "8/1 "%02x ""   "8/1 "%02x "' -e '"    "8/1 "%_p""|"8/1 "%_p""\n"' masternospaces.txt
00000000 (0x00000000)    4e 6f 20 43 4f 57 20 65   6e 64 69 6e 67 0d 0a 45    No COW e|nding..E
00000016 (0x00000010)    6e 64 69 6e 67 20 69 6e   20 43 4f 57 0d 0a          nding in| COW..

注意 dos 格式的行结尾:0d 0a

更改行结尾

你可以看到这里或者这里对于使用各种工具更改行结尾的各种方法,但对于一次性的事情,您始终可以使用 vi/vim :

vim masternospaces.txt
:set fileformat=unix
:wq

grep 不做任何改变

如果您只想grep匹配无论行结尾如何,您始终可以像这样指定行结尾:

grep 'COW[[:cntrl:]]*$' masternospaces.txt

如果显示空行,您可以使用以下-v选项检查您是否确实匹配某些内容cat

grep 'COW[[:cntrl:]]*$' masternospaces.txt | cat -v

我个人最喜欢的

您还可以使用 grep 和标准化输出sed

sed -n '/COW^M*$/{;s/^M//g;p;};' masternospaces.txt

在哪里通过键盘^M输入获得。Ctrl-V Ctrl-M

希望这可以帮助!

答案2

另一种删除\rgrep 之前的方法:

... | dos2unix | egrep 'COW$' | ...

我喜欢它非常清晰,因为我记不住[[:cntrl:]]很长时间的事情。

答案3

尽管您可以将“标准”正则表达式语法与 grep 一起使用(如@user43791的回答),grep 还有其他标识符来表示输入边界。

整行的开头和结尾的匹配器是\`(反引号)(而不是^)和\'(撇号)(而不是$)。

因此,对于您的原始命令,您将使用: grep "COW\'" masternospaces.txt

旁注:还需要注意的是,?+将会按字面意思处理,除非您使用\?和来转义它们\+,使它们成为正则表达式风格的选择器对应项。

来源:grep正则表达式语法

答案4

“COW$”当bash为grep设置参数时,它被解释为“COW”,其中将“$”视为“”,因为$是转义符号。当 $ 没有任何内容时,bash shell 将其解释为空字符串,因此您应该使用 grep 'COW$' masternospaces.txt 代替。

相关内容