Поиск и печать значения внутри тегов с использованием скрипта

У меня есть файл, как это. abc.txt

<ra><r>12.34</r><e>235</e><a>34.908</a><r>23</r><a>234.09</a><p>234</p><a>23</a></ra>
<hello>sadfaf</hello>
<hi>hiisadf</hi>
<ra><s>asdf</s><qw>345</qw><a>345</a><po>234</po><a>345</a></ra>

Что я должен сделать, это я должен найти <ra> тег и внутри <ra> тег есть <a> тег, в котором я должен хранить значения внутри некоторых переменных, которые мне нужно обрабатывать дальше. Как мне это сделать?

значения внутри тега внутри тега:
34.908,234.09,23
345,345

2 ответа

Решение

Это awk следует сделать:

cat file
<ra><r>12.34</r><e>235</e><a>34.908</a><r>23</r><a>234.09</a><p>234</p><a>23</a></ra><a>12344</a><ra><e>45</e><a>666</a></ra>
<hello>sadfaf</hello>
<hi>no print from this line</hi><a>256</a>
<ra><s>asdf</s><qw>345</qw><a>345</a><po>234</po><a>345</a></ra>

awk -v RS="<" -F">" '/^ra/,/\/ra/ {if (/^a>/) print $2}' file
34.908
234.09
23
666
345
345

Это нужно позаботиться, если есть несколько <ra>...</ra> группы в одну строку.


Небольшая вариация:

awk -v RS=\< -F\> '/\/ra/ {f=0} f&&/^a/ {print $2} /^ra/ {f=1}' file
34.908
234.09
23
666
345
345

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

awk -v RS="<" -F">" '   # This sets record separator to < and gives a new line for every <
/^ra/,/\/ra/ {          # within the record starting witn "ra" to record ending with "/ra" do
    if (/^a>/)          # if line starts with an "a" do
    print $2}'          # print filed 2

Чтобы увидеть, как работает смена RS, попробуйте:

awk -v RS="<" '$1=$1' file
ra>
r>12.34
/r>
e>235
/e>
a>34.908
/a>
r>23
/r>
a>234.09
/a>
p>234
...

Чтобы сохранить его в переменной, вы можете сделать так, как предложил BMW:

var=$(awk ...)
var=$(awk -v RS=\< -F\> '/\/ra/ {f=0} f&&/^a/ {print $2} /^ra/ {f=1}' file)
echo $var
34.908 234.09 23 666 345 345
echo "$var"
34.908
234.09
23
666
345
345

Так как его много значений, вы можете использовать массив:

array=($(awk -v RS=\< -F\> '/\/ra/ {f=0} f&&/^a/ {print $2} /^ra/ {f=1}' file))
echo ${array[2]}
23
echo ${var2[0]}
34.908
echo ${var2[*]}
34.908 234.09 23 666 345 345

Использование утверждений gnu grep Lookahead и Lookbehind нулевой длины

grep -oP "(?<=<ra>).*?(?=</ra>)" file |grep -Po "(?<=<a>).*?(?=</a>)"

объяснение

  • первый grep получит содержимое в ra тег. Даже если в одной строке есть несколько тегов ra, их все равно можно идентифицировать.

  • Второй grep получает содержимое в a тег

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