Извлеките и удалите первое вхождение XML tag несколько раз

awk 'NR==FNR{a[$1]=$2; next} $2 in a {$2=a[$2]} {print}'  file2.txt file1.txt
P       SNP:
0.266234        1:11008
0.266234        1:11012
0.340042        1:13110
0.86724 1:10020
0.86724 1:10055
0.127269        1:1327
1
05.06.2017, 21:17
3 ответа

Использование синтаксических анализаторов XML является правильным способом работы с XML-документами.

xmlstarletрешение:

xmlstarlet sel -t -c '//capacity[1]' -n yourxml > temp.txt 
&& xmlstarlet ed -d '//capacity[1]' yourxml > tmp.xml && mv tmp.xml yourxml 

cat temp.txt
<capacity><name>45.90</name>
<index>0</index>
<value_type>String</value_type>
<ignore_case_flag>1</ignore_case_flag>
<hidden_flag>0</hidden_flag>
<exclude_from_parse_flag>1</exclude_from_parse_flag>
</capacity>

  • xmlstarlet sel -t -c '//capacity[1]' -n yourxml > temp.txt— извлекает первое объявление тега capacityи перенаправляет вывод в temp.txt

  • xmlstarlet ed -d '//capacity[1]' yourxml > tmp.xml— удаляет первый тег capacityиз документа (через -dудалить действие) и перенаправляет измененное содержимое документа во временный файл tmp.xml

  • mv tmp.xml yourxml— заменить исходный xml-документ его измененной версией

6
27.01.2020, 23:13

Поскольку у вас нет синтаксического анализатора xml, попробуйте этот с помощью gnu awk:

$ awk -v RS="<subcolumns>|</capacity>" 'NR==2{gsub(/^\n/,"");print $0 RT;exit}' file.xml
<capacity><name>45.90</name>
<index>0</index>
<value_type>String</value_type>
<ignore_case_flag>1</ignore_case_flag>
<hidden_flag>0</hidden_flag>
<exclude_from_parse_flag>1</exclude_from_parse_flag>
</capacity>

Почему это работает:
в awk вы можете установить собственный разделитель записей/строк. В нашем примере мы используем либо , либо

. В результате с помощью настраиваемого разделителя записей мы можем получить следующий формат:

$ awk -v RS="<subcolumns>|</capacity>" '{gsub(/^\n/,"");print NR,$0 RT}' file.xml
1 <subcolumns>
2 <capacity><name>45.90</name>
<index>0</index>
<value_type>String</value_type>
<ignore_case_flag>1</ignore_case_flag>
<hidden_flag>0</hidden_flag>
<exclude_from_parse_flag>1</exclude_from_parse_flag>
</capacity>
3 <capacity><name>57.09</name>
<index>1</index>
<value_type>String</value_type>
<ignore_case_flag>1</ignore_case_flag>
<hidden_flag>0</hidden_flag>
<exclude_from_parse_flag>1</exclude_from_parse_flag>
</capacity>
4 <capacity><name>55</name>
<index>2</index>
<value_type>String</value_type>
<ignore_case_flag>1</ignore_case_flag>
<hidden_flag>0</hidden_flag>
<exclude_from_parse_flag>1</exclude_from_parse_flag>
</capacity>
5 </subcolumns>

PS: NR = число или запись /Линия. RT = используется разделитель записей.

Соответственно, вы можете распечатать любой блок , изменив номер NR:

$ awk -v RS="<subcolumns>|</capacity>" 'NR==4{gsub(/^\n/,"");print $0 RT}'
<capacity><name>55</name>
<index>2</index>
<value_type>String</value_type>
<ignore_case_flag>1</ignore_case_flag>
<hidden_flag>0</hidden_flag>
<exclude_from_parse_flag>1</exclude_from_parse_flag>
</capacity>

Соответственно, если вам нужно пропустить секцию ( т.е. первый раздел емкости) вы можете просто сделать:

$ awk -v RS="<subcolumns>|</capacity>" '{gsub(/^\n/,"")}NR!=2{print $0 RT}'
<subcolumns>
<capacity><name>57.09</name>
<index>1</index>
<value_type>String</value_type>
<ignore_case_flag>1</ignore_case_flag>
<hidden_flag>0</hidden_flag>
<exclude_from_parse_flag>1</exclude_from_parse_flag>
</capacity>
<capacity><name>55</name>
<index>2</index>
<value_type>String</value_type>
<ignore_case_flag>1</ignore_case_flag>
<hidden_flag>0</hidden_flag>
<exclude_from_parse_flag>1</exclude_from_parse_flag>
</capacity>
</subcolumns>
2
27.01.2020, 23:13
chunk=2; # specify the tag chunk number here which must be > 0
perl -l -0777ne "print((m{(<capacity>.*?</capacity>)}sg)[${chunk:-1}-1])" yourxmlfile

Результаты

<capacity><name>57.09</name>
<index>1</index>
<value_type>String</value_type>
<ignore_case_flag>1</ignore_case_flag>
<hidden_flag>0</hidden_flag>
<exclude_from_parse_flag>1</exclude_from_parse_flag>
</capacity>
0
27.01.2020, 23:13

Теги

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