Несколько многострочных регулярных выражений в Bash - PullRequest
3 голосов
/ 22 января 2010

Я пытаюсь сделать довольно простой анализ строки в bash-скрипте. По сути, у меня есть файл, который состоит из нескольких многострочных полей. Каждое поле окружено известным верхним и нижним колонтитулами.

Я хочу извлечь каждое поле отдельно в массив или аналогичный, как это

>FILE=`cat file`
>REGEX="@#@#@#[\s\S]+?@#@#@"
> 
>if [[$FILE =~ $REGEX ]] then
>   echo $BASH_REMATCH
>fi

FILE:

@#@#@#################################
this is field one
@#@#@#
@#@#@#################################
this is field two
they can be any number of lines
@#@#@#

Теперь я почти уверен, что проблема в том, что bash не сопоставляет символы новой строки с "."

Я могу сопоставить это с "pcregrep -M", но, конечно, весь файл будет соответствовать. Могу ли я получить один матч за раз от pcregrep?

Я не против использования встроенного Perl или аналогичного.

Заранее спасибо

Ответы [ 4 ]

3 голосов
/ 22 января 2010

если у вас есть поглазеть

awk 'BEGIN{ RS="@#*#" }
NF{
    gsub("\n"," ") #remove this is you want to retain new lines
    print "-->"$0 
    # put to array
    arr[++d]=$0
} ' file

выход

$ ./shell.sh
--> this is field one
--> this is field two they can be any number of lines
1 голос
/ 07 января 2014

Язык TXR выполняет многострочное сопоставление всего документа, связывает переменные и (с опцией -B «привязки дампа») выдает правильно экранированные назначения переменных оболочки, которые могут быть eval -редакторПоддерживаются массивы.

Символ @ является специальным, поэтому его необходимо удвоить, чтобы он соответствовал буквально.

$ cat fields.txr
@(collect)
@@#@@#@@#################################
@  (collect)
@field
@  (until)
@@#@@#@@#
@  (end)
@  (cat field)@# <- catenate the fields together with a space separator by default
@(end)

$ txr -B fields.txr data
field[0]="this is field one"
field[1]="this is field two they can be any number of lines"

$ eval $(txr -B fields.txr data)
$ echo ${field[0]}
this is field one
$ echo ${field[1]}
this is field two they can be any number of lines

Синтаксис @field соответствует всей строке.Они собраны в список, поскольку он находится внутри @(collect), а списки собраны в списки списков, потому что он вложен в другой @(collect).Внутренний @(cat field), однако, сводит внутренние списки к одной строке, поэтому мы в итоге получаем список строк.

Это «классический TXR»: как он был изначально спроектирован и использован, вызванныйidea:

Почему бы нам не сделать так, чтобы здесь-документы работали задом наперед и не выполняли синтаксический разбор текста из переменных в переменные?

Это неявное выделение совпадающих переменных по умолчанию,в синтаксисе оболочки по умолчанию продолжает оставаться поддерживаемым поведением, даже несмотря на то, что язык стал гораздо более мощным, поэтому меньше необходимости в интеграции со сценариями оболочки.

0 голосов
/ 22 января 2010
begin="@#@#@#################################"
end="@#@#@#"
i=0
flag=0

while read -r line
do
    case $line in
        $begin)
            flag=1;;
        $end)
            ((i++))
            flag=0;;
        *)
            if [[ $flag == 1 ]]
            then
                array[i]+="$line"$'\n'    # retain the newline
            fi;;
     esac
done < datafile

Если вы хотите сохранить линии маркеров в элементах массива, переместите оператор присваивания (с его тестом флага) в верхнюю часть цикла while перед case.

0 голосов
/ 22 января 2010

Я бы построил что-то около awk. Вот первое доказательство концепции:

awk '
    BEGIN{ f=0; fi="" }
    /^@#@#@#################################$/{ f=1 }
    /^@#@#@#$/{ f=0; print"Field:"fi; fi="" }
    { if(f==2)fi=fi"-"$0; if(f==1)f++ }
' file
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...