1

У меня есть файл, который имеет много строк в формате:

bc("STG1/Phone") = {type=bana_pub; cbb=12.354; abb=0.0}`

Я ищу, чтобы извлечь cbb=12.354; , В настоящее время я делаю следующее:

cat input_file.txt | grep cbb | awk -F " " '{ print $4 }'`

Проблема в том, что мой подход зависит от местоположения, то есть предполагается, что это всегда 4-е поле. Как извлечь текст в форме cbb= зная после = это может быть любая длина и точка с запятой ; не является обязательным. Единственная гарантия, которую я имею, состоит в том, что термин cbb=12.354; будет окружен пробелами, если это поможет. Файл в будущем может иметь формат:

bc("STG1/Phone") = {type=bana_pub; cbb=12.354; abb=0.0}
bc("STG1/Phone") = {type=bana_pub;  abb=0.0; cbb=12.354}

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

Спасибо в ожидании вашей помощи.

4 ответа4

2

Решение:

grep -Eo 'cbb=[^;}]+'

Давайте проверим это:

$ grep -Eo 'cbb=[^;}]+' <<<'bc("STG1/Phone") = {type=bana_pub; cbb=12.354; abb=0.0}`'
$ cbb=12.354

Объяснение:

Когда вы используете ... | grep cbb | ... вы используете базовое регулярное выражение. Продвинутое регулярное выражение не так сложно.

Опция -E для расширенного регулярного выражения, полезна для того, чтобы не избегать некоторых метасимволов. -o для печати только то, что соответствует grep вместо всей строки.

Регулярное выражение cbb=[^;}]+ будет таким же для любого другого cmd, а не только для grep.

cbb= является фиксированной строкой, метасимвола там нет (c сопровождается b т. д.)

[^;}]+ квадратные скобки ограничивают набор символов в одной позиции. Каретка в начале означает отрицательный набор символов. Знак плюс означает один или несколько символов. Таким образом, он будет соответствовать любому символу, по крайней мере, одному, пока не найдет ; или }

Вот хорошая ссылка, чтобы узнать больше о регулярных выражениях:https://www.regular-expressions.info/characters.html

2

Это работает и не зависит от позиции:

grep cbb input_file.txt | awk -F "cbb=" '{ print $2 }'| awk -F ";" '{print "cbb=" $1}'

Сначала он выбирает только строки, содержащие cbb , затем использует строку cbb= качестве разделителя и, наконец, использует ; в качестве разделителя полей добавляем строку cbb = к окончательному результату.

0

Вы также можете использовать sed (так как sed вызывается только один раз, он должен быть быстрее)

sed -n 's/^.*\(cbb=[0-9\.]*\).*$/\1/p' sample.txt

Где sample.txt - ваш входной файл. Отметьте только числовое значение ([0-9.]), Чтобы устранить возможную проблему с необязательной точкой с запятой.

0

В этом случае grep является правильным инструментом для работы. Тем не менее, я решил добавить:

  • Perl

    perl -lane 'print $1 if /(cbb=[^;}]+)/' input_file.txt
    
  • AWK

    awk 'match($0,/cbb=[^;}]+/,m) {print m[0]}' input_file.txt
    
  • Sed

    sed -rn 's/.*(cbb=[^;}]+).*/\1/p' input_file.txt
    

Благодарность Пауло за понимание того, что имел в виду ОП:

после = это может быть любая длина и точка с запятой ; не является обязательным. Единственная гарантия, которую я имею, состоит в том, что термин cbb=12.354; будет окружен пробелами

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .