Парсинг и фильтрация строк в bash по регулярным выражениям

  • Михаил
  • 12 мин. на прочтение
  • 186
  • 13 Nov 2022
  • 13 Nov 2022

Примеры парсинга и фильтрации строк в bash - grep, =~ (BASH_REMATCH).
 

Trim

echo ' string wirh spaces  ' | tr -d ' '

Разделение строки

Разбить строки по заданному разделителю:

echo "1;2;3" | tr ";" "\n"

Разделить строку и получить 2ю часть:

str='one;two;three'
echo $str | cut -d ';' -f2 # two
my_var="$( cut -d ';' -f 2 <<< "$str" )";

Извлечь первую строку (first line):

cat file | head -n 1

Позитивные и негативные проверки

Подробнее: http://bit.ly/1sBvdoD

(?<=) Позитивная ретроспективная проверка (positive lookbehind assertion) !Доступна только в PCRE режиме. Продолжает поиск только если слева от текущей позиции в тексте находится заключённое в скобки выражение

(?=)  Положительная опережающая проверка (positive lookahead assertion). Продолжает поиск только если справа от текущей позиции в тексте находится заключённое в скобки выражение.

(?<!) Негативная ретроспективная проверка (negative lookbehind assertion). Продолжает поиск только если слева от текущей позиции в тексте не находится заключённое в скобки выражение.

(?!)  Негативная опережающая проверка (negative lookahead assertion). Продолжает поиск только если справа от текущей позиции в тексте не находится заключённое в скобки выражение.

Пример использования утилитой grep:

echo 'text<b>bold</b> end, not bold' | grep -Poi '(?<=text<b>).+(?=\<)' ## bold

Поиск и фильтрация строк

GREP

Помните!

Любой grep'подобный regex поиск не позволяет захватывать (capture) группу вхождений подобно $BASH_REMATCH в операторе сравнения =~.

Найти текст по маске regex:

echo 'text<b>bold</b> end, not bold' | grep -Poi '(?<=text<b>).+(?=\<)'  ## bold
ifconfig ppp0 | grep -Po 'P-t-P:\K([\d\.]+)'  ## 10.64.64.64
-i    регистро-независимый поиск
-o    выводить не всю строку, а лишь найденный шаблон
-P    --perl-regexp, шаблон как Perl совместимое регулярное выражение
-E    --extended-regexp, шаблон как расширенное регулярное выражение (ERE)
\K    захватывать только выражение в (скобках)

BASH_REMATCH

Разобрать строку на части по regex шаблону:

if [[ "$line" =~ ^\ ?(--platform) ]]; then
  # Установить $match, если $BASH_REMATCH пустой
  if [[ $BASH_REMATCH != '' ]]; then
    match=("${BASH_REMATCH[@]}")
  fi

  echo $line
  printf -- '%s\n' "${arr[@]}" ## Или: echo ${match[@]}
  echo ${match[1]}
fi

Примечание

В zsh вместо переменной с вхождениями BASH_REMATCH доступен массив $match. В примере ниже я устанавливаю в $match одну из доступных переменных.

Поиск в нескольких строках:

... | pcregrep -iM '<annot.*?>(.|\n)+?</annot'