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