2012-03-26 30 views
10

我试图循环遍历文件中的每一行,找到并提取以${开头并以}结尾的字母。因此,我期待的最终产出仅为SOLDIRTEMP(来自inputfile.sh)。使用sed/regex在同一行上提取多个实例

我已经尝试使用以下脚本,但它似乎匹配并只提取模式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" 

回答

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

关于'grep -P'的TIL,谢谢。 – 2012-03-26 10:31:05

+0

非常有用。谢谢! – noumenon 2016-01-24 20:56:04

2

这可能会为你(只适用于特定的输入线,但也许)工作:

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

它的工作。谢谢。 – user1292603 2012-03-26 09:59:12

+0

在这种情况下,您可能想要接受答案。 – 2012-03-27 07:25:39

0

使用SED并不那么糟糕,因为我认为这会是从一个单一的线提取多个匹配,但它仍然是相当深奥而难以阅读:

$ 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 

而且都在同一行:

sed -En 's#\$\{([^}]+)\}#\a\1\n#;/\n/!b;s#.*\a##;P;D' 

由于POSIX扩展正则表达式不支持非贪婪量词或在括号表达式中添加换行符我已将BEL字符(\a)用作前缀末尾的标记而不是换行符。可以使用换行符,但是第二次替换必须是可疑的s#.*\n(.*\n.*)##,这可能涉及正则表达式引擎的病态回溯。

相关问题