SED скопировать определенный раздел в разные файлы

Я пытался создать сценарий, который экономит мое время. Вот что я хочу сделать: у меня есть один большой XML-файл с разделами, скажем, он выглядит следующим образом:

some text
.....
HEAD
context A
TAIL
some text
.....
HEAD
context B
TAIL
....
some text
....
HEAD
context C
TAIL
....
some text

Мне нужно вырезать раздел с помощью context A и перейти к файлу contextA, а затем context B в файл contextB и т. Д. (Все файлы должны содержать синтаксис HEAD context x TAIL). Проблема в том, что все контексты начинаются и заканчиваются одним и тем же регулярным выражением (HEAD и TAIL). Я могу вырезать все разделы в один файл, но этого недостаточно.

Можете ли вы мне помочь?

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

 some text 1
 <config>
 1
 2
 3
 </config>
 some text 2
 <config>
 4
 5
 6
 </config>
 some text 3
 <config>
 7
 8
 9
 </config>
 some text 4

и я хочу, чтобы файл назывался :

«первый», который содержит:

 <config>
 1
 2
 3
 </config>

«второй», который содержит:

 <config>
 4
 5
 6
 </config>

и т. Д.

1
задан 17 January 2018 в 14:49

4 ответа

Легче сделать это с awk:

awk -v RS="HEAD\n" -v FS="\n" 'NR>1{print "HEAD\n" $0 > $1".txt"}' ex

Примечания:

  • RS="HEAD\n" регистры разделяются "HEAD\n"
  • FS="\n" каждое поле является строкой
  • NR>1{print "HEAD\n" $0 > $1} для всего регистра кроме первого запишите это в файл, названный полем 1 - "1$"

ОБНОВЛЕНИЕ: для нового вопроса:

awk -v RS="<config>\n" -F"</config>" 'NR>1{print RS $1 FS > "conf-"NR-1}' ex

Выводы конфигурации хранятся в файлах, названных как: "conf-1"

1
ответ дан 17 January 2018 в 14:49

Если вы действительно не можете использовать правильный синтаксический анализатор XML для этого , то я бы предложил awk, например

awk '/^HEAD/ {p=1; ++n} p {print > "context"n} /^TAIL/ {p=0}' file.xml

выведет секции HEAD ... TAIL в числово увеличивающиеся имена файлов context1, context2 и т. Д.

Для упрощения сортировки вы можете немного улучшить ее, создав числовой префикс фиксированной ширины, например

.
$ awk '/^HEAD/ {p=1; outfile = sprintf("context%03d", ++n)} p {print > outfile} /^TAIL/ {p=0}' file.xml

$ head context*
==> context001 <==
HEAD
context A
TAIL

==> context002 <==
HEAD
context B
TAIL

==> context003 <==
HEAD
context C
TAIL
1
ответ дан 17 January 2018 в 14:49

Мое использование сценария awk:

#!/bin/bash
for i in $(seq -w $(<"$1" grep -cx "$2")); do
  <"$1" >$i awk -va=$i -vb="$2" -vc="$3" '$0~b{d++;e=1}d==a&&e==1;$0~c{e=0}'
done

Сохраните его как, например. myscript.sh, сделайте это исполняемым файлом, перейдите к Вашему onebig.xml и назовите его как это:

/path/to/myscript.sh onebig.xml HEAD TAIL

Это отключит каждый раздел от onebig.xml начало HEAD и окончание TAIL и сохраните их как 1, 2, …, если существует меньше чем 10 разделов, как 01, 02, …, если существует 10 - 99 разделов, как 001, 002, …, если существует 100 - 999 разделов и т.д.

Короткие объяснения

  • <"$1" grep -cx "$2" – происшествия количества HEAD в onebig.xml, скажем, это 3
  • for i in $(seq -w 3); do …; done – цикл по каждому происшествию от 1 до 3, seq-w опция добавляет конечные нули при необходимости
  • <"$1" >$i – читайте из onebig.xml и запишите в файл, названный как текущее количество
  • awk -va=$i -vb="$2" -vc="$3" – запустить awk и присвойте три переменные, a будучи количеством, b быть HEAD и c быть TAIL
  • $0~b{d++;e=1} – если текущая строка содержит содержание b (= HEAD) увеличение d одним и набором e=1
  • d==a&&e==1 – если d равняется a (= текущее количество) и e равняется 1 затем распечатайте текущую строку (print подразумеваемое действие; по существу это: если это после aпроисшествие th HEAD и мы между HEAD и TAIL затем печать)
  • $0~c{e=0} – если текущая строка содержит содержание c (= TAIL) набор e=0
0
ответ дан 17 January 2018 в 14:49

Пожалуйста, проверьте, поможет ли вам приведенный ниже скрипт:

#!/bin/bash
for x in {A..Z}; do
    # check if the pattern exists in the file
    if grep -qF "context $x" file.txt; then
        # Store the lines between the 2 patterns including the matching lines in a text file
        awk '/context '$x'/,/TAIL/' file.txt > context$x.txt
    else
       echo "Sorry this pattern does not exists in file"
    fi
done
0
ответ дан 17 January 2018 в 14:49

Другие вопросы по тегам:

Похожие вопросы: