对于 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
另一种删除\r
grep 之前的方法:
... | dos2unix | egrep 'COW$' | ...
我喜欢它非常清晰,因为我记不住[[:cntrl:]]
很长时间的事情。
答案3
尽管您可以将“标准”正则表达式语法与 grep 一起使用(如@user43791的回答),grep 还有其他标识符来表示输入边界。
整行的开头和结尾的匹配器是\`
(反引号)(而不是^
)和\'
(撇号)(而不是$
)。
因此,对于您的原始命令,您将使用:
grep "COW\'" masternospaces.txt
旁注:还需要注意的是,?
和+
将会按字面意思处理,除非您使用\?
和来转义它们\+
,使它们成为正则表达式风格的选择器对应项。
来源:grep
正则表达式语法
答案4
“COW$”当bash为grep设置参数时,它被解释为“COW”,其中将“$”视为“”,因为$是转义符号。当 $ 没有任何内容时,bash shell 将其解释为空字符串,因此您应该使用 grep 'COW$' masternospaces.txt 代替。