正则表达式跨多行非贪婪地匹配,直到以特定字符串开头的行

问题描述 投票:0回答:2

我将自己回答这个问题,但这整天使我感到满意,尽管在其他地方有解释,但我认为我应该将其发布在解决方案中。

我遇到了一种情况,我需要替换一些跨越多行的文本。不难发现有关如何跨多行进行匹配的线索。我的情况有点困难,因为我需要在多行中通配符匹配任何字符,直到在第一个不缩进的右括号处停止为止。

出于演示目的,我制作了一个示例文件,该文件具有令我难以接受的功能:

开始文件:

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成为更好的选择。

regex perl wildcard multiline non-greedy
2个回答
0
投票

似乎我既需要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修饰符又需要吃草。因此,如果有人有更好的答案,我会标记为那个,而不是我自己的。


0
投票

据我所知,您希望匹配字符串的一部分

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

demo

标志s允许.*匹配换行符。我知道标志m指示解析器将锚点^$分别视为行的开头和结尾(大概与字符串的开头和结尾相对)。

© www.soinside.com 2019 - 2024. All rights reserved.