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

Regex: How to match pattern only once?

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

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

我确实设法让它与以下正则表达式一起工作:

sed -e '/^#/d;s/\(.+\)=\(.+\)/def  ""\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 在这一行中出现了两次。 请问我怎样才能避免这种情况?

此致,

只需在您的命令中删除 g

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

而不是

sed -e '/^#/d;s/\(.+\)=\(.+\)/def  ""\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

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

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

def SYMBOL "SYMBOL"

def SYMBOL "SYMBOL"

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

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

请注意,我将第二个 </code> 更改为 <code>,因为我认为这就是您的意思。我还避免使用扩展正则表达式量词 +,转而使用更便携的基本正则表达式量词 *