Извлечь несколько вхождений в одной строке, используя sed / regex - PullRequest
10 голосов
/ 26 марта 2012

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

Я попытался использовать следующий скрипт, но, похоже, он соответствует и извлекает только второе вхождение шаблона TEMP.Я также попытался добавить g в конце, но это не помогает.Может кто-нибудь, пожалуйста, дайте мне знать, как сопоставить и извлечь оба / несколько вхождений в одной строке?

inputfile.sh:

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

скриптш:

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

Ответы [ 3 ]

9 голосов
/ 26 марта 2012

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

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

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

Подавая твою строку, я получаю

$ echo "SOLPORT=\`grep -A 4 '[LocalDB]' \${SOLDIR}/solidhac.ini | grep \${TEMP} | awk '{print $2}'\`" | grep -oP '(?<=\${).*?(?=})'
SOLDIR
TEMP
2 голосов
/ 26 марта 2012

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

sed 's/[^$]*\(${[^}]\+}\)[^$]*/\1\t/g;s/$[^{$]\+//g'
1 голос
/ 09 апреля 2017

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...