извлечь текст между двумя словами, используя sed - PullRequest
0 голосов
/ 27 апреля 2020

Я хочу извлечь текст в переменной оболочки, которая находится между двумя соответствующими словами / символами, как показано ниже.

Входная строка-

extract='sometext Query State: FINISHED\n Query Status: OK\n soonnnnnnnnnnnn Query State: STARTING\n'

Я хочу чтобы извлечь состояние запроса, которое находится между текстом 'Query State' и первым появлением '\ n'

. Я использовал ниже выражение sed-

query_state=$(echo $extract | sed 's/.*Query State: \(.*\)\\n .*/\1/')

но я получаю вывод в виде - FINISHED\n Query Status: OK, в основном, вышеприведенное дает все, что между словами «Статус запроса» и последним появлением «\ n».

Итак, Я изменил на выражение sed, как показано ниже, чтобы получить вывод 'FINISHED'

query_state=$(echo $extract | sed 's/.*Query State: \(.*\)\\n Query Status.*/\1/')

Но вышеприведенное выражение сильно зависит от текста «Статус запроса». Как я могу изменить выражение так, чтобы оно получалось точно при первом появлении '\ n'?

Обновление: я хочу извлечь состояние запроса, которое находится между первым появлением текста 'Состояние запроса' с последующим первым появлением '\ n'

-Спасибо

Ответы [ 3 ]

2 голосов
/ 27 апреля 2020

grep решение (поскольку вы только ищете совпадение, вы не хотите ничего редактировать):

$ echo "$extract"
sometext Query State: FINISHED\n Query Status: OK\n soonnnnnnnnnnnn

$ echo "$extract" | grep -oP '(?<=Query State: ).*?(?=\\n)'
FINISHED

Объяснение:

-o Возврат только совпавшая подстрока (это возвратит все совпадения, по одному на строку)

-P Для perl -совместимых регулярных выражений; необходим для обхода, а также для ленивого квантификатора

(?<= ... ) lookbehind : совпадение должно начинаться с позиции, следующей сразу за последним символом (в данном случае пробелом) между открывающей последовательностью (?<= и закрывающая скобка.

.*? ноль или более символов ( любой символов), как можно меньше . *? называется lazy (или non-жадный ) квантификатор.

(?=\\n) lookahead : аналогично lookhehind. Backsla sh необходимо экранировать.

EDIT :

Если фрагмент «Query State: ...» может появляться в самом конце строки, не завершается маркером \n, и если в этом случае состояние все еще должно быть возвращено, регулярное выражение необходимо изменить следующим образом:

$ echo $extract
sometext Query State: FINISHED

$ echo $extract | grep -oP '(?<=Query State: ).*?((?=\\n)|$)'
FINISHED

Обратите внимание на чередование в смотрим в будущее: ищем подстроку \n или конец входной строки; любой из них будет работать.

1 голос
/ 27 апреля 2020

Для короткого случая вы можете рассмотреть дополнительный вызов sed:

echo "$extract" | sed -n 's/\\n/\n/g; s/.*Query State: //p'

Можете ли вы рассказать что-нибудь о возможных значениях состояния? Другое решение может быть что-то вроде

echo "$extract" | sed -r 's/.*Query State: ([A-Za-z ]*).*/\1/'
0 голосов
/ 27 апреля 2020

Это работает.

extract='sometext Query State: FINISHED\n Query Status: OK\n soonnnnnnnnnnnn' 

echo "$extract" | sed 's/.*Query State: \([^\\n]\+\).*$/\1/'

Вывод

FINISHED

Работает с awk

echo "$extract" |  awk -F'[: \\\\n]+' '{print $4}'
...