Извлечь строки после шаблона - PullRequest
1 голос
/ 04 апреля 2019

У меня есть 50 файлов в папке, и все они имеют общий шаблон "^^".Я хочу напечатать все после "^^" и добавить имя файла и распечатать все извлеченные строки в один выходной файл.Хотя мой код отлично работает с одним файлом, он не работает со всеми файлами.

awk '/\^^/{getline; getline; print FILENAME; print}' *.txt > output

Пример

1.txt

     ghghh hghg 
       ghfg hghg hjg
            jhhkjh 
    kjhkjh kjh

^^ 
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz

2.txt

hghjhg hgj 
 jhgj

            jhgjh kjgh

        jhg

^^ 
bbbbbbbbbbbbbbbbbbbbbbb

Желаемый output.txt

1.txt
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
2.txt
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb

Мой фактический вывод

1.txt
ghghh hghg
1.txt
zzzzzzzzzzzzzzzzzzzzzzzzzzzzz

Ответы [ 8 ]

1 голос
/ 04 апреля 2019
$ awk 'FNR==1{print FILENAME; f=0} f; $1=="^^"{f=1}' *.txt
1.txt
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
2.txt
bbbbbbbbbbbbbbbbbbbbbbb
1 голос
/ 04 апреля 2019

Чтобы напечатать строку после ^^, попробуйте:

$ awk 'f{print FILENAME ORS $0; f=0} /\^\^/{f=1}' *.txt
1.txt
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
2.txt
bbbbbbbbbbbbbbbbbbbbbbb

Как это работает:

  • f{print FILENAME ORS $0; f=0}

    Если переменнаяf имеет значение true (отличное от нуля), выведите имя файла, разделитель выходной записи и текущую строку.Затем установите f обратно на ноль.

  • /\^\^/{f=1}

    Если текущая строка содержит ^^, установите f на единицу.

0 голосов
/ 05 апреля 2019

Это может работать для вас (GNU sed):

sed -s '1,/^^^/{/^^^/F;d}' file1 file2 file3 ... >fileOut
0 голосов
/ 04 апреля 2019

Используя некоторые ответы и комментарии к предыдущему вопросу по этой теме, вы также можете использовать grep -A и отформатировать вывод с помощью sed.

$ grep -A100 '^^' *.txt | sed '/\^^/d;/--/d;s/-/\n/'
1.txt
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
2.txt
bbbbbbbbbbbbbbbbbbbbbbb

Предполагая, что достаточно 100 строк, и вы неУ меня нет собственных дефисов.

Если вам нужна только одна строка, используйте -A1

0 голосов
/ 04 апреля 2019

Следующие выходные данные выводятся только в том случае, если у нас есть файл, соответствующий нашему шаблону:

awk 'FNR==1 { f=0 }; f; /\^\^/ { f=1; print FILENAME }' *.txt > output
  1. Сбрасывать флаг f для каждого нового файла.
  2. Печатать, если f
  3. Установить f и print FILENAME, если мы сопоставим наш шаблон.

Этот выводит FILENAME независимо от соответствующего шаблона:

awk 'FNR==1 { f=0; print FILENAME }; f; /\^\^/ { f=1 }' *.txt > output

Мы можем настроить сопоставление с образцом на шаге 3 в соответствии с тем, что требуется ... точное соответствие, например, можно сделать с помощью $0=="^^".

0 голосов
/ 04 апреля 2019

пусть имена ваших файлов от 1 до 50 с типом txt

for f in {1..50}.txt
{
  sed -nE "/^\^\^\s*$/{N;s/.+\n(.+)/$f\n\1/p}" $f>$f.result.txt
}
0 голосов
/ 04 апреля 2019

использование awk:

awk 'FNR==1{print FILENAME} FNR==1,/\^\^/{next}1' *.txt

Где:

  • печатать FILENAME, когда FNR == 1
  • FNR==1,/\^\^/{next}: все строки между FNR == 1 и первой строкой, соответствующей ^^, будут пропущены
  • 1 в конце, чтобы напечатать остальные строки после совпавшей ^^ строки
0 голосов
/ 04 апреля 2019

Мне нравится более подход "bash (ish)".

grep -Hn '^^' *.txt |
cut -d: -f1,2 --output-delimiter=' ' |
while read f n; do echo $f; tail $f -n+$((n+1)); done
  • grep -Hn сообщит номер строки вашего паттерна.
  • С cut мыполучите только необходимые поля, как нам нужно.
  • В цикле мы read две информации в переменные, чтобы использовать их свободно, как нам нужно.
  • tail не может читать нетолько последние N строк, но также и все строки из +N, если вы используете сигнал плюс.
  • Мы можем выполнить арифметическую операцию внутри $((...)), чтобы пересечь линию шаблона.

И это решает вашу проблему.И он может печатать все строки после шаблона, а не только следующую.

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