regex 打印包含图案的行,其前面是包含不同图案的另一行

mec1mxoz  于 2023-04-13  发布在  其他
关注(0)|答案(4)|浏览(126)

macOS 13.3 Ventura因此BSD版本的grep,awk等。
如何搜索和打印包含一个模式的行,而该行必须在包含不同模式的另一行之前?
文本包含这样的行(用于参考的前导大写字母,...==不相关的字符)。

...                   # An indeterminate number of lines.
A ... "model" = \< ...
  ...                   # An indeterminate number of lines.
B ... PXS4@0 ...
  ...                   # An indeterminate number of lines.
C ... "model" = \< ...
  ...                   # An indeterminate number of lines.
D ... PXS2@0 ...
  ...                   # An indeterminate number of lines.
E ... "model" = \< ...
  ...                   # An indeterminate number of lines.
F ... PXS1@0 ...
  ...                   # An indeterminate number of lines.
G ... "model" = \< ...
  ...                   # An indeterminate number of lines.
H ... "model" = \< ...
  ...                   # An indeterminate number of lines.

只有前面带有PXS:digit:@0的行带有“model”的行才应该出现:

C ... "model" = \< ...
E ... "model" = \< ...
G ... "model" = \< ...

AFAICT macOS的awk & grep中的正则表达式不支持look-behind和look-ahead。
我以为这会找到一个匹配的PXS......然后找到/打印模型......但它打印行“A”:

awk '/(PXS\[\[:digit:\]\]@0 )+?model" = \</ { print }'

这也很接近,但打印行“A”。既然它打印“A”,我不明白为什么它不打印“H”。

grep -e ".\*PXS\[\[:digit:\]\]@0 " -e ".\*model" = \<"" | grep -v -e ".\*PXS\[\[:digit:\]\]@0 "

请指教!

dbf7pr2w

dbf7pr2w1#

MacOs
perl -n0e 'print $_ =~ /PXS[[:digit:]]@0.*\n.*\n/g' filename | perl -p -e 's/PXS[[:digit:]]@0[^\n]*\n//g'

第一步:只留下PXS[[:digit:]]@0和后面的行。
第二步:删除带有PXS[[:digit:]]@0的行

Linux
grep -zoP 'PXS[[:digit:]]@0.*\n.*\n' filename | sed -z -E 's/PXS[[:digit:]]@0[^\n]*\n//g'

Grep查找包含PXS[[:digit:]]@0的行及其后续行,sed从输出中删除包含PXS[[:digit:]]@0的行。

velaa5lx

velaa5lx2#

你可以试试

awk '/PXS[0-9][@]0/{getline;if(match($0,"model")){ print;}}'

/PXS[0-9][@]0/将匹配前缀行
getline;将读取下一行(并填充$0)
match($0,"model")将查看该行是否包含regexp 'model'

erhoui1w

erhoui1w3#

谢谢你给我指引了正确的方向。这给了我C、E和G线。
我在awk中使用了一个循环来查找PXS[[:digit:]]@0的第一行,使用了一个子循环来查找"model" = <的第二行。如果第一行存在,则第二行将存在(但不直接在第一行之后)。
我还设置了awk的分隔符,因为我想要的最终值在"model" = \<"之后和">之前。

awk -F'<"|">' 'BEGIN {while (getline != 0) if ($0 ~ /PXS[[:digit:]]@0 /) {while (getline != 0) if ($0 ~ /"model" = </){print $2; break;}}}'

我喜欢在一个awk命令中完成整个事情,我的另一个解决方案需要5个管道grep。

dwthyt8l

dwthyt8l4#

$ awk '/model/ && match(prevline,/PXS[0-9]@0/){print} {prevline=$0}' file
C ... "model" = \< ...
E ... "model" = \< ...
G ... "model" = \< ...

相关问题