Извлечение нескольких вхождений в одной строке с помощью sed/regex

Я пытаюсь пропустить каждую строку в файле и найти и извлечь буквы, начинающиеся с ${ и заканчивающиеся на }. Таким образом, в качестве конечного результата я ожидаю только SOLDIR и TEMP (от inputfile.sh).

Я попытался использовать следующий script, но кажется, что он соответствует и извлекает только второе вхождение шаблона 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"  

Ответ 1

Могу ли я предложить решение grep?

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

Он использует Perl-стиль поисковые утверждения и лениво сопоставляет что-либо между '${' и '}'.

Подавая свою линию, я получаю

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

Ответ 2

Это может работать для вас (но, возможно, только для вашей конкретной строки ввода):

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

Ответ 3

Извлечение нескольких совпадений из одной строки с помощью 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 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.*)##, которая может включать в себя патологическое количество обратного отслеживания с помощью механизма регулярных выражений.