使用sed / regex在同一行上提取多个匹配项

时间:2012-03-26 09:20:31

标签: regex sed

我正在尝试遍历文件中的每一行,并查找并提取以${开头并以}结尾的字母。因此,作为最终输出,我只期望SOLDIRTEMP(来自inputfile.sh)。

我尝试使用以下脚本,但似乎匹配并仅提取模式TEMP的第二次出现。我也尝试在最后添加g,但它没有帮助。请问有谁可以让我知道如何在同一行上匹配和提取两个/多个事件?

inputfile.sh:

.  
.  
SOLPORT=\`grep -A 4 '\[LocalDB\]' \${SOLDIR}/solidhac.ini | grep \${TEMP} | awk '{print $2}'\`  
.  
.  

script.sh:

infile='inputfile.sh'  
while read line ; do    
  echo $line | sed 's%.*${\([^}]*\)}.*%\1%g'  
done < "$infile"  

3 个答案:

答案 0 :(得分:9)

我可以提出grep解决方案吗?

grep -oP '(?<=\${).*?(?=})'

它使用Perl风格的lookaround assertions并且懒惰地匹配'${''}'之间的任何内容。

给你的线路,我得到

$ echo "SOLPORT=\`grep -A 4 '[LocalDB]' \${SOLDIR}/solidhac.ini | grep \${TEMP} | awk '{print $2}'\`" | grep -oP '(?<=\${).*?(?=})'
SOLDIR
TEMP

答案 1 :(得分:2)

这可能对您有用(但可能仅适用于您的特定输入行):

sed 's/[^$]*\(${[^}]\+}\)[^$]*/\1\t/g;s/$[^{$]\+//g'

答案 2 :(得分:1)

使用sed从一行中提取多个匹配并不像我想象的那么糟糕,但它仍然相当深奥且难以阅读:

l

一切都在一条线上:

$ echo 'Hello ${var1}, how is your ${var2}' | sed -En '
    # Replace ${PREFIX}${TARGET}${SUFFIX} with ${PREFIX}\a${TARGET}\n${SUFFIX}
    s#\$\{([^}]+)\}#\a\1\n#
    # Continue to next line if no matches.
    /\n/!b
    # Remove the prefix.
    s#.*\a##
    # Print up to the first newline.
    P
    # Delete up to the first newline and reprocess what's left of the line.
    D
'
var1
var2

由于POSIX扩展正则表达式不支持非贪婪量词或在括号表达式中放置换行符,因此我使用sed -En 's#\$\{([^}]+)\}#\a\1\n#;/\n/!b;s#.*\a##;P;D' 字符(BEL)作为结尾处的哨兵前缀而不是换行符。可以使用换行符,但第二次替换必须是有问题的\a,这可能涉及正则表达式引擎的病态回溯量。