为什么行尾 $ 锚不能与 grep 命令一起使用,即使行前 ^ 锚是?

DTa*_*hio 29 grep newlines

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

当我进入

grep "^COW" masternospaces.txt
Run Code Online (Sandbox Code Playgroud)

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

但是当我进入

grep "COW$" masternospaces.txt
Run Code Online (Sandbox Code Playgroud)

我希望得到一个以 COW 结尾的单词列表(有很多这样的单词),并且根本没有返回任何内容。

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

知道这里会发生什么吗?

use*_*791 33

正如@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
Run Code Online (Sandbox Code Playgroud)

使用输出,检查行尾: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..
Run Code Online (Sandbox Code Playgroud)

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

更改行尾

您可以在此处此处查看使用各种工具更改行尾的各种方法,但对于一次性的事情,您始终可以使用 vi/vim :

vim masternospaces.txt
:set fileformat=unix
:wq
Run Code Online (Sandbox Code Playgroud)

在不改变任何东西的情况下使用 grep

如果你只想grep匹配行尾,你总是可以像这样指定行尾:

grep 'COW[[:cntrl:]]*$' masternospaces.txt
Run Code Online (Sandbox Code Playgroud)

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

grep 'COW[[:cntrl:]]*$' masternospaces.txt | cat -v
Run Code Online (Sandbox Code Playgroud)

我个人的最爱

您还可以使用sed以下命令对输出进行 grep 和标准化:

sed -n '/COW^M*$/{;s/^M//g;p;};' masternospaces.txt
Run Code Online (Sandbox Code Playgroud)

where^M是通过Ctrl-V Ctrl-M在键盘上打字获得的。

希望这可以帮助!


小智 7

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

... | dos2unix | egrep 'COW$' | ...
Run Code Online (Sandbox Code Playgroud)

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