Я пытался создать сценарий, который экономит мое время. Вот что я хочу сделать: у меня есть один большой 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>
и т. Д.
Легче сделать это с 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"
Если вы действительно не можете использовать правильный синтаксический анализатор 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
Мое использование сценария 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
Пожалуйста, проверьте, поможет ли вам приведенный ниже скрипт:
#!/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