我想过滤掉所有以香蕉线开头的行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
意味着该表达式可以吃换行符。我不太熟悉-v
pcregrep 中的实现方式,不知道为什么它不是相反的,但我很确定这就是原因。
如果您将文件更改为:
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
否定条件