我将自己回答这个问题,但这整天使我感到满意,尽管在其他地方有解释,但我认为我应该将其发布在解决方案中。
我遇到了一种情况,我需要替换一些跨越多行的文本。不难发现有关如何跨多行进行匹配的线索。我的情况有点困难,因为我需要在多行中通配符匹配任何字符,直到在第一个不缩进的右括号处停止为止。
出于演示目的,我制作了一个示例文件,该文件具有令我难以接受的功能:
开始文件:
cat << EOF > test.txt
server {
abcdefg blablablabla
pizza
#blablablabla
blablablabla {
zazazazazaza
}
turtles
#}
ninjas
blablablabla
} #comments that might or might not be here
server {
blablablabla
blablablabla
blablablabla
blablablabla
}
zabzazab
EOF
这是我想要的输出。请注意,我要匹配的括号既不是第一个也不是最后一个出现的右括号。它唯一的区别在于它是我比赛开始后一行的第一个}
:
server {
wxyz
server {
blablablabla
blablablabla
blablablabla
blablablabla
}
zabzazab
我希望可以。但是用0777
混合会去除行首和结尾处的标记,因此它不起作用:
~# perl -0777 -pe 's/(abcdefg(.*?)(^}.*$))/wxyz/gs' test.txt
server {
abcdefg blablablabla
pizza
#blablablabla
blablablabla {
zazazazazaza
}
turtles
#}
ninjas
blablablabla
} #comments that might or might not be here
server {
blablablabla
blablablabla
blablablabla
blablablabla
}
zabzazab
匹配行的开始/结束,同时还遇到了问题:
~# perl -0777 -pe 's/(abcdefg(.*?)(}))/wxyz/gs' test.txt
server {
wxyz
turtles
#}
ninjas
blablablabla
} #comments that might or might not be here
server {
blablablabla
blablablabla
blablablabla
blablablabla
}
zabzazab
所以有什么方法可以使正则表达式匹配字符串和出现在行首的{
的第一个实例?我也愿意使用sed,但我认为搜索的非贪婪性质会使perl成为更好的选择。
似乎我既需要s标志,也需要m标志,并且需要吃喝:
~# perl -0777 -pe 's/(abcdefg(.+?)(\n}))/wxyz/sm' test.txt
server {
wxyz #comments that might or might not be here
server {
blablablabla
blablablabla
blablablabla
blablablabla
}
我仍然不太明白为什么我既需要m
修饰符又需要吃草。因此,如果有人有更好的答案,我会标记为那个,而不是我自己的。
据我所知,您希望匹配字符串的一部分
server {
abcdefg blablablabla
pizza
#blablablabla
blablablabla {
zazazazazaza
}
turtles
#}
ninjas
blablablabla
} #comments that might or might not be here
server {
... blablablabla
}
...
以"abcdefg"
开头并在行"} #comments that might or might not be here"
的末尾,条件是"abcdefg"
在缩进之后开始一行,并且该行之前是行"server {"
。然后,您将用另一个字符串替换匹配的文本。
您可以使用以下正则表达式匹配要替换的文本:
/^server +\{\r?\n +(abcdefg.+?^\}.*?$)/sm
标志s
允许.*
匹配换行符。我知道标志m
指示解析器将锚点^
和$
分别视为行的开头和结尾(大概与字符串的开头和结尾相对)。