регулярное выражение в Bash возвращает результаты, отличные от ruby - PullRequest
0 голосов
/ 15 января 2019

Я пытаюсь извлечь группы совпадений из строки - я использовал Rubular , чтобы создать шаблон:

\[(.*?)\]

Который в ruby, кажется, извлекает ожидаемые группы для следующей строки:

1547156981784: подача [Code128] с [this_is_a_test] размером [12ms] [385B] с использованием [http://barcodeapi.org/index.html] для [1.2.3.4] через [5.6.7.8]

1: Code128
2: this_is_a_test
3: 12ms
4: 385B
5: http://barcodeapi.org/index.html
6: 1.2.3.4
7: 5.6.7.8

Однако эта проблема заключается в том, что я пытаюсь реализовать это регулярное выражение в скрипте Bash для анализа файла журнала:

reg='\[(.*?)\]'
while read line; do
  if [[ $line =~ $reg ]]; then
    echo ${BASH_REMATCH[1]};
  fi
done < $log

Но результаты не такие, как у рубина / рубулара; в Bash группа совпадений # 1 содержит всю строку, за исключением самых первых и самых последних скобок; для той же строки журнала bash возвращает только одно совпадение:

1: Code128 ] with [ this_is_a_test ] in [ 12ms ] size [ 385B ] using [ http://barcodeapi.org/index.html ] for [ 1.2.3.4 ] via [ 5.6.7.8

Вопрос существо,

Почему два двигателя дают разные результаты? Как правильно разделить группы с помощью Bash?

1 Ответ

0 голосов
/ 15 января 2019

Несколько выпусков:

  1. В Bash нет глобального соответствия;
  2. Вам необходимо вручную зациклить несколько совпадений в Bash и вручную управлять индексом строки;
  3. В ERE нет не жадного квантификатора, используемого в регулярных выражениях Bash, поэтому .*? не работает так же, как в Ruby.

Вы можете использовать это как начало:

while read line; do
    while [[ $line =~ ([^\[]*)\[([^\]]*)\] ]]; do 
        i=${#BASH_REMATCH}
        line=${line:i}
        echo "${BASH_REMATCH[2]}"
    done
done < file 

Печать:

 Code128 
 this_is_a_test 
 12ms 
 385B 
 http://barcodeapi.org/index.html 
 1.2.3.4 
 5.6.7.8 

И у вас будет значительно меньше головной боли, если вы просто используете Perl / GNU grep / Ruby / etc для создания списка совпадений и затем используете Bash для циклического перебора , :

while read m; do
    echo "Match: $m"
done < <(ggrep -oP '(?<=\[)(.*?)(?=\])' file)  # GNU grep is ggrep here

Если ваш код должен быть положительно POSIX, используйте awk:

$ awk -v RS=[ -v FS=] 'NR>1{print $1}' file
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...