pcregrep 排除多行正则表达式比需要的多吃一行

pcregrep 排除多行正则表达式比需要的多吃一行

我想过滤掉所有以香蕉线开头的行banana以及以香蕉线之后的空格开头的所有行。我在用pcregrep。考虑以下文件fruits.txt

apple
banana starts matching
 this line should match
 this too
 and this
mango
pomelo

pcregrep很高兴找到我想要的:

ars@ars-thinkpad ~/tmp/tmp $ pcregrep -M  'banana.*\n(\s.*\n)*' fruits.txt 
banana starts matching
 this line should match
 this too
 and this

但是,如果我尝试排除这些行,pcregrep也会吃芒果,这不好:

ars@ars-thinkpad ~/tmp/tmp $ pcregrep -M -v 'banana.*\n(\s.*\n)*' fruits.txt 
apple
pomelo

为什么?

答案1

您在正则表达式中使用\s意味着该表达式可以吃换行符。我不太熟悉-vpcregrep 中的实现方式,不知道为什么它不是相反的,但我很确定这就是原因。

如果您将文件更改为:

apple
banana starts matching
 this line should match
 this too
 and this

mango

pomelo

即使没有-v,匹配看起来也不是您想要的。

$ pcregrep  -M 'banana.*\n(\s.*\n)*' fruits.txt
banana starts matching
 this line should match
 this too
 and this

mango

pomelo

如果确实只有行开头的一个空格需要匹配,我建议将 更改\s为一个或多个空格" +"

当我将正则表达式更改为'banana.*\n( +.*\n)*' It 时,它会以我认为更正确的方式匹配(常规和反向)。[ \t]+如果也允许使用制表符,也许可以使用。

答案2

这样的任务更适合awk我认为

$ awk '!/^ /{f=0} /^banana/{f=1} f' fruits.txt 
banana starts matching
 this line should match
 this too
 and this
$ awk '!/^ /{f=0} /^banana/{f=1} !f' fruits.txt 
apple
mango
pomelo
  • 设置标志的顺序有助于轻松打印或否定正在搜索的特定行,因为条件也!/^ /满足以 开头的行banana
  • !/^ /{f=0}如果行不以空格开头,则清除标志
  • /^banana/{f=1}如果行开头为则设置标志banana
  • f打印匹配条件的行,同时!f否定条件

相关内容