Bash совместимое регулярное выражение (с группами) - PullRequest
1 голос
/ 10 марта 2020

Я пытаюсь сделать простой скрипт с регулярным выражением. Это регулярное выражение работает в текстовых редакторах и онлайн-проверках регулярных выражений. Но я не могу найти способ заставить его работать на bash.

Кстати, мне нужно захватить группы.

Пример текста:

2020-03-06 10:00:07 Test2: <?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soape...
2020-03-06 10:00:13 Test2: <?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soape...

Это мой сценарий. Он читает каждую строку и создает файл с именем DATE_HOUR. xml, заполненный текстом до конца строки (после его форматирования):

#!/bin/bash
: ${1?"USO: $0 NOMBRE-DEL-ARCHIVO"} #If no args passed

regex="^(\d*-\d*-\d*)\s(\d*:\d*:\d*)\s(\w*): (.*)$" #This one is working on editors

mkdir -p out
while read line
do
   if [[ $line =~ $regex ]] #IT NEVER ENTERS HERE
    then
        date="${BASH_REMATCH[1]}"   #DATE
        time="${BASH_REMATCH[2]}"   #TIME
        time="${time/:/-}"          #REPLACE : with -
        name="${BASH_REMATCH[3]}"   #I DO NOT USE IT BY NOW
        text="${BASH_REMATCH[4]}"   #TEXT
        echo $text | xmllint --format - > out/$date"_"$time.xml
    fi
done < $1

Я пробовал это регулярное выражение, но он наверняка имеет ошибки:

regex="^([[:digit:]]{4}-[[:digit:]]{2}-[[:digit:]]{2}) ([[:digit:]]{2}:[[:digit:]]{2}:[[:digit:]]{2}) ([[a-zA-Z0-9]]{1,}): (*{1,})$"

Спасибо.

Ответы [ 2 ]

3 голосов
/ 10 марта 2020

Во-первых, вы не можете использовать сокращение "Perl -style", такое как \d и \s в Bash. Ваша последняя попытка близка, но содержит несколько ошибок, таких как [[a-zA-Z0-9]] (должна быть только одна пара []) и *{1,} (не на 100% ясно, что это делает, но это не то, что вы хотите!).

Этот шаблон можно использовать вместо:

regex='([0-9]{4}-[0-9]{2}-[0-9]{2}) ([0-9]{2}:[0-9]{2}:[0-9]{2}) ([a-zA-Z0-9]+): (.*)'

Я использую [0-9] для сопоставления цифр - вы можете использовать [[:digit:]] вместо этого, но это не похоже на то, что вам нужна поддержка для любых символов вне диапазона 0-9. Я также заменил \s на простой пробел (вы можете использовать [[:blank:]] для сопоставления пробелов или табуляции, если это возможно).

Что касается якорей ^ и $, они, вероятно, вам не нужны:

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

Тестирование:

$ line='2020-03-06 10:00:07 Test2: <?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soape...'
$ regex='([0-9]{4}-[0-9]{2}-[0-9]{2}) ([0-9]{2}:[0-9]{2}:[0-9]{2}) ([a-zA-Z0-9]+): (.*)'
$ [[ $line =~ $regex ]] && echo yes
yes
$ printf '%s\n' "${BASH_REMATCH[@]}"
2020-03-06 10:00:07 Test2: <?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soape...
2020-03-06
10:00:07
Test2
<?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soape...
1 голос
/ 10 марта 2020

Вместо головной боли с регулярным выражением, почему бы не попробовать awk:

while read line
do
filename=$(awk '{print $1"_"$2}' <<< "$line")
awk '{$1="";$2="";$3=""; gsub(/^[[:space:]]+/,"",$0); print}'  <<< "$line" |xmllint --format - >out/${filename}.xml
done < $1

Если вы не хотите использовать двоеточие в имени файла, вы можете заменить строку следующим образом:

filename=$(awk '{gsub(/:/,"",$2); print $1"_"$2}' <<< "$line")

То, что делает этот код, является примером. Сначала это делает l oop через все строки (из вашего кода). Затем я присваиваю filename первую и вторую переменные, объединенные с нижним кодом.

Далее через секунду awk Я присваиваю пустую строку первым 3 токенам, затем gsub заменяем пробелы (между первым и вторым токенами, между вторым и третьим токеном и третьим токеном и четвертым токеном). Если я этого не сделаю, некоторые версии xmllint будут жаловаться. Затем я печатаю строку. Конструкция <<< "$line" означает использовать для содержимого $ line и создать обработчик файлов и использовать его в качестве входного файла.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...