Извлечение подстроки из строки в квадратных скобках, где подстрока может содержать пробелы - PullRequest
2 голосов
/ 06 мая 2020

У меня есть приложение, в котором не реализован полезный API, и единственный способ получить определенную информацию - это проанализировать вывод строки. Это оказывается очень болезненным ...

Я пытаюсь добиться этого в bash на SLES12.


Учитывая, что у меня есть следующие строки:

QMNAME(QMTKGW01)                                          STATUS(Running)
QMNAME(QMTKGW01)                                          STATUS(Ended normally)

Я хочу извлечь значение STATUS, ie «Нормально завершено» или «Выполняется». Обратите внимание, что линейная структура может перемещаться, поэтому я не могу рассчитывать на то, что «STATUS» будет вторым полем. так что

echo "QMNAME(QMTKGW01)  STATUS(Running)" | sed "s/^.*STATUS(\(\S*\)).*/\1/"

Это работает для "Работает", но не для "Нормально завершено"

Я пробовал переключать \ S * на [\ S \ s] * в обоих "grep -o "и" sed ", но похоже, что это повреждает все регулярное выражение.

Ответы [ 3 ]

2 голосов
/ 06 мая 2020

Это чисто проблема с регулярным выражением, выполнив \S, вы запросили сопоставление непробельных символов внутри (..), но в случае неудачи есть пробел между ними, который не соответствует определенной грамматике. Сделайте это простым, явно вызывая символы для соответствия внутри (..) как [a-zA-Z ]*, т.е. ноль или более символов верхнего и нижнего регистра и пробелов.

sed 's/^.*STATUS(\([a-zA-Z ]*\)).*/\1/'

Или используйте классы символов [:alnum:], если хотите числа тоже

sed 's/^.*STATUS(\([[:alnum:] ]*\)).*/\1/'
1 голос
/ 06 мая 2020
sed 's/.*STATUS(\([^)]*\)).*/\1/' file

Вывод:

Running
Ended normally
0 голосов
/ 07 мая 2020

Извлечение подстроки, соответствующей заданному шаблону, является задачей grep, а не sed. Мы должны использовать sed, когда мы должны редактировать входную строку. (Многие люди используют sed и даже awk только для извлечения подстрок, но, на мой взгляд, это расточительно.)

Итак, вот решение grep. Нам нужно сделать некоторые предположения (в любом решении) относительно ваших входных данных - некоторые легко расслабляются, другие - нет. В вашем примере слово STATUS всегда пишется с заглавной буквы, и сразу за ним следует открывающая скобка (без пробела, без двоеточия и c.). Эти предположения можно легко ослабить. Что еще более важно, и обойти его нелегко: нет скобок вложенных . Вам понадобится самая длинная подстрока символов, не являющихся закрывающими скобками, после открывающей скобки, независимо от того, какие они есть. * Параметры команды: o, чтобы вернуть только совпавшую подстроку; P для использования расширений Perl (маркер \K и опережающий просмотр). Регулярное выражение: мы ищем границу слова (\b) - так что слово STATUS является полным словом, а не частью более длинного слова, такого как SUBSTATUS; затем слово СТАТУС и открывающая скобка. Это требуется для сопоставления, но \K указывает, что эта часть сопоставленной строки не будет возвращена в выводе. Затем мы ищем ноль или более символов незакрывающих скобок ([^)]*), и мы требуем, чтобы за ними следовала закрывающая скобка, но закрывающая скобка также не включается в возвращаемую строку. Это «взгляд вперед» (конструкция (?= ... )).

...