正则表达式:如何只匹配模式一次?

时间:2015-01-27 09:00:49

标签: regex sed

我正在尝试从.config文件中提取数据(使用kconfig生成)。 默认格式为:

SYMBOL=y (in case of a bool)
SYMBOL="str" (in case of a string)

我确实设法使用以下正则表达式:

sed -e '/^#/d;s/\(.+\)=\(.+\)/def \1 "\1"\n/g' configfile > formattedfile

它适用于除此之外的任何情况:

SYMBOL="http://my.domain/toast?id=150"

结果,我的输出文件中有:

def SYMBOL="http://my.domain/toast?id "SYMBOL="http://my.domain/toast?id="

因为模式XXX = XXX在此行中出现两次。 我该怎么办呢?

此致

3 个答案:

答案 0 :(得分:1)

问题是.+ 贪婪:它会尝试匹配最长的字符串。这延伸到第二个=。由于标识符不能包含=字符,因此最好在匹配第一部分时更具体:

sed -e '/^#/d;s/^\([^=]*\)=\(.*\)/def \1 \2\n/' configfile > formattedfile

请注意,我将第二个\1更改为\2,因为我认为这就是您的意思。我还避免使用扩展正则表达式量词+来支持更便携的基本正则表达式量词*

答案 1 :(得分:0)

只需将g放入您的命令中:

sed -e '/^#/d;s/\(.+\)=\(.+\)/def \1 "\1"\n/'
                                            ^

而不是

sed -e '/^#/d;s/\(.+\)=\(.+\)/def \1 "\1"\n/g'
                                            ^

来自info sed

`g'
     Apply the replacement to _all_ matches to the REGEXP, not just the
     first.

见另一个例子:

$ echo "hello" | sed 's/l/X/'   #without g
heXlo
$ echo "hello" | sed 's/l/X/g'  #with g
heXXo

答案 2 :(得分:0)

您需要转义+符号,并将第一个.+转为[^=]\+,因为.+贪婪且与最后=符号匹配。

$ sed -e '/^#/d;s/\([^=]\+\)=\(.\+\)/def \1 "\1"\n/g' file
def SYMBOL "SYMBOL"

def SYMBOL "SYMBOL"

def SYMBOL "SYMBOL"