Как извлечь линии между узорами? - PullRequest
0 голосов
/ 18 августа 2011

У меня есть файл с форматом вроде:

[PATTERN]
line1
line2
line3
.
.
.
line
[PATTERN]
line1
line2
line3
.
.
.
line
[PATTERN]
line1
line2
line3
.
.
.
line

Я хочу извлечь из этого файла следующие блоки:

[PATTERN]
line1
line2
line3
.
.
.
line

Примечание. Число строк между 2 [PATTERN] может различаться, поэтому не может зависеть от количества строк.

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

Как это сделать с помощью сценариев оболочки?

Ответы [ 2 ]

2 голосов
/ 18 августа 2011

Предполагается, что вы используете bash в качестве оболочки. Для других оболочек реальное решение может быть другим.

Предположим, ваши данные в data:

i=0 ; cat data  | while read line ; do \
  if [ "$line" == "[PATTERN]" ] ; then \
    i=$(($i + 1)) ; touch file.$i ; continue ; \
  fi ; echo "$line" >> file.$i ; \
done

Измените [PATTERN] на ваш фактический шаблон разделения.

Это создаст файлы file.1, file.2 и т. Д.

Редактировать: ответ на запрос о решении awk:

awk '/^\[PATTERN\]$/{close("file"f);f++;next}{print $0 > "file"f}' data

Идея состоит в том, чтобы каждый раз открывать новый файл [PATTERN] (пропуская эту строку - команда next), и записывать все последующие строки в этот файл. Если вам нужно включить [PATTERN] в ваши сгенерированные файлы, удалите команду next.

Обратите внимание на экранирование [ и ], которые имеют особое значение для регулярных выражений. Если ваш шаблон не содержит их, вам не нужно убегать. Рекомендуется использовать ^ и $, поскольку они привязывают ваш шаблон к началу и концу строки, что вам обычно требуется.

0 голосов
/ 18 августа 2011

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

#!/bin/bash
file=$1
gp_cnt=-1
i=-1

while read line
do
  # Match pattern
  if [[ "$line" == "[PATTERN]" ]]; then
    let "gp_cnt +=1"
    # If this is not the first match process group
    if [[ $gp_cnt -gt 0 ]]; then
      # Process the group
      echo "Processing group #`expr $gp_cnt - 1`"
      echo ${parsed[*]}
    fi
    # Start new group
    echo "Pattern #$gp_cnt catched"
    i=0
    unset parsed
    parsed[$i]="$line"

    # Other lines (lines before first pattern are not processed)
  elif [[ $gp_cnt != -1 ]]; then
    let "i +=1"
    parsed[$i]="$line"
  fi
done < <(cat $file)

# Process last group
echo "Processing group #$gp_cnt"
echo ${parsed[*]}

Мне не нравится обработка последней группы изпетля ...

...