regex 在正则表达式中,我如何匹配直到一个字符或另一个字符无限,但不分组的最后一个字符?

c90pui9n  于 2023-01-27  发布在  其他
关注(0)|答案(2)|浏览(155)

这是我的字符串,我希望正则表达式在组1返回“bash”,在组2返回“585602”(Pid值)

Name:     bash
Umask:  0022
State:  S (sleeping)
Tgid:   585602
Ngid:   0
Pid:    585602
PPid:   585598
TracerPid:  0
Uid:    1000    1000    1000    1000
Gid:    1000    1000    1000    1000
FDSize: 256
Groups: 150 962 970 985 987 990 996 998 1000 
NStgid: 585602
NSpid:  585602
NSpgid: 585602
NSsid:  585602
VmPeak:     8708 kB
VmSize:     8708 kB
...

我现在拥有的是

Name:\t *(.*)\n(.|\n)*?Pid:\t *(.*)\n

不幸的是,我看到第二个匹配的组是“Pid”的P之前的一个换行符,第三个是Pid值。我感觉问题出在正则表达式的(.|\n)部分,但是如果我去掉括号,那么它会组合很多我不想要的东西。我怎么才能只把bash和pid值作为组呢?

jdg4fx2g

jdg4fx2g1#

在第二个组中会得到一个换行符,因为您正在重复(.|\n)*,并且重复捕获组的值将保存最后一次迭代的值。
Pid:之前的字符是一个换行符,即您看到的捕获组的值。
请注意,使用(.|\n)*是不可取的,因为重复中会出现交替。更好的方法可能是(如果支持)使用内联标志(?s)来使点匹配换行符,使用字符类[\s\S]*或在编程语言中设置该标志来使点匹配换行符。
您可以使用2个捕获组(实际上并不需要3个组),将Pid作为数字进行匹配,并在第一个捕获组中至少匹配一个非空白字符\S
如果要考虑线的起点和终点,可以使用^开始模式,使用$结束模式

\bName:\t *(\S.*)\n[\s\S]*?^Pid:\t *(\d+)\b

参见regex101 demo
或者如@anubhava建议可选地重复整行,然后换一个新行,非贪婪,如(?:.*\n)*而不是[\s\S]*?

\bName:\t *(.*)\n(?:.*\n)*?Pid:\t *(\d+)\b

参见另一个regex101 demo

jq6vz3qz

jq6vz3qz2#

perl中,使用slurp模式引导管柱-

$: perl -ne 'BEGIN{$/=undef} /Name:\s+(\S+).*\nPid:\s+(\S+)/ms; print "$1 $2\n";'<<<"$str"
bash 585602

相关问题