我正在开发一个 shell 脚本的增强功能,它可以读取文件并处理它。基本上,输入文件包含一个标题记录,后面跟着一些详细记录。我只想从文件中获取头记录。
$ cat sample_file.txt
header1,header2,header3,header4
value1,value2,value3,value4
现有脚本使用以下命令从文件中获取标头:
$ cat sample_file.txt | head -1 | egrep -o '[[:print:]]' | tr '\n' '\0'
header1,header2,header3,header4$
我不知道egrep -o '[[:print:]]'
这里该做什么。因为即使没有命令,egrep
也可以像这样输入
按原样打印标题
$ cat sample_file.txt | head -1
header1,header2,header3,header4
或者打印标题而不在末尾换行
$ cat sample_file.txt | head -1 | tr '\n' '\0'
header1,header2,header3,header4$
的手册页egrep
告诉了下面的内容,但不清楚何时[[:print:]]
应该使用。
最后,在括号表达式中预定义了某些命名的字符类,如下所示。它们的名称是不言自明的,它们是 [:alnum:]、[:alpha:]、[:cntrl:]、[:digit:]、[:graph:]、[:lower:]、[:print:] 、[:punct:]、[:space:]、[:upper:] 和 [:xdigit:]。例如,[[:alnum:]] 表示 [0-9A-Za-z],但后一种形式取决于 C 语言环境和 ASCII 字符编码,而前者独立于语言环境和字符集。 (请注意,这些类名称中的方括号是符号名称的一部分,除了界定方括号列表的方括号之外还必须包含方括号。)大多数元字符在列表中会失去其特殊含义。要包含文字 ],请将其放在列表的第一位。类似地,要包含文字 ^,请将其放置在除开头之外的任何位置。最后,要包含文字 - 将其放在最后。
您能帮我理解egrep '[[:print:]]'
选项的用法以及我们在哪里使用它吗?
答案1
括号表达式类似于[abc]
,它匹配其中的任何一个字符。例如[abc]
会匹配a
or b
,但不匹配d
or :
。可以在括号表达式中使用字符类,以将整个类添加到括号表达式匹配的集合中。[[:print:]]
将匹配单个可打印字符,保留控制字符、换行符和制表符。egrep
,或者最好是grep -E
,将打印与给定模式匹配的任何行,并使用-o
仅打印匹配的部分,每行一个。
例如,使用 时[:alpha:]
,冒号被省略:
$ echo ab:c | egrep -o '[[:alpha:]]'
a
b
c
因此,实际上,egrep -o '[[:print:]]'
将打印输入中的每个可打印字符,每行一个。然后tr '\n' '\0'
将换行符更改为 NUL 字节,这样您就可以获得所有中间带有 NUL 的可打印字符。我不确定这是否有意义,因为 NUL 并不比控制字符更好处理。如果您在例如less
或中打开结果数据vim
,您将看到 NUL 打印为^@
,可能是彩色的。
同样,cat sample_file.txt | head -1 | tr '\n' '\0'
不消除换行符,它用 NUL 替换它。
我不确定这里的目标是什么,但要删除任何换行符和制表符,您可以使用tr -d
:
... | tr -d '\n\t'
并删除所有不可打印的字符-d
以-c
补充(反转)匹配的字符集:
... | tr -dc '[:print:]'
(请注意,它tr
并不像正则表达式中那样采用外部括号。实际上, to 的参数tr
就像正则表达式括号表达式的内部。)
答案2
您可以在中找到解释GNU 的字符类和括号表达式文档:
'[:print:]'
可打印字符:'[:alnum:]'、'[:punct:]' 和空格。
如果您需要整个标头,则不需要任何解析命令,例如egrep
等。
从man egrep
:
此外,变体程序egrep、fgrep 和rgrep 分别与grep -E、grep -F 和grep -r 相同。这些变体已被弃用,但提供它们是为了向后兼容。
所以基本上egrep [[:print:]]
与 相同grep -E [[:print:]]
,只有当您需要时才需要扩展正则表达式 (ERE),但该模式[[:print:]]
不是其中之一。