lac*_*der 3 grep regular-expression
给定一个文件“test.log”,其中包含以下内容:
line1 Patient 123 45566
line2 Patient 432
line3 Patient 234 456
line4 Patient 321
line5
Run Code Online (Sandbox Code Playgroud)
我正在尝试选择line 2
并line 4
使用这种模式:
grep "Patient\s\d+\s" test.log
# but this works testing at https://rubular.com/
Run Code Online (Sandbox Code Playgroud)
不起作用,这也不起作用:
grep "Patient\s\d+\n" test.log
# but this works testing at https://regexr.com/47qd5
Run Code Online (Sandbox Code Playgroud)
我究竟做错了什么?
GNUgrep
默认使用基本正则表达式 (BRE),但它也允许您使用扩展正则表达式 (ERE) 和 Perl 兼容的正则表达式 (PCRE)。
请注意,BRE 和 ERE 都不支持\s
也不支持\d
,但它们具有相似的功能。从man grep
:
最后,在括号表达式中预定义了某些命名的字符类,如下所示。它们的名称是不言自明的,分别是
[:alnum:]
、[:alpha:]
、[:cntrl:]
、[:digit:]
、[:graph:]
、[:lower:]
、[:print:]
、、、 和。例如,表示当前语言环境中数字和字母的字符类。在 C 语言环境和 ASCII 字符集编码中,这与. (请注意,这些类名中的方括号是符号名称的一部分,除了界定方括号表达式的方括号之外,还必须包含方括号。)大多数元字符在方括号表达式内会失去其特殊含义。要包含文字,请将其放在列表的第一位。同样,要包含文字,请将其放置在除开头以外的任何位置。最后,将其文字放在最后。[:punct:]
[:space:]
[:upper:]
[:xdigit:]
[[:alnum:]]
[0-9A-Za-z]
]
^
-
例子:
$ grep -E '^[[:digit:]]+$' << 'EOF'
> foo
> 123
> bar
> EOF
123
Run Code Online (Sandbox Code Playgroud)
您还可以使用 PCRE,因为它支持\s
和\d
:
$ grep -P '^\d+$' << 'EOF'
> foo
> 123
> bar
> EOF
123
Run Code Online (Sandbox Code Playgroud)
\n
不起作用在 Unix 中,每个\n
分隔一行。grep
打印与给定模式匹配的行。在这种情况下,匹配\n
本身没有意义。
您可以使用$
来匹配行尾:
$ grep -E 'foo bar$' << 'EOF'
> foo
> foo bar
> foo bar baz
> EOF
foo bar
Run Code Online (Sandbox Code Playgroud)
或传递-z
/--null-data
选项来激活“多行”模式(您需要一些额外的解决方法来完全匹配您想要的):
$ grep -Poz '(?<=\n)?foo bar\n' << 'EOF'
> foo
> foo bar
> foo bar baz
> EOF
foo bar
Run Code Online (Sandbox Code Playgroud)
最后一个\s
将匹配line 1
andline 3
而不是line 2
and line 4
:
$ grep -P 'Patient\s\d+\s' << 'EOF'
> line1 Patient 123 45566
> line2 Patient 432
> line3 Patient 234 456
> line4 Patient 321
> line5
> EOF
line1 Patient 123 45566
line3 Patient 234 456
Run Code Online (Sandbox Code Playgroud)