Выберите строку с помощью grep или awk

#regex #awk #grep

#регулярное выражение #awk #grep

Вопрос:

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

 <port protocol="tcp" portid="9050"><state state="open" reason="syn-ack" reason_ttl="64"/><service name="tor-socks" method="table" conf="3"/></port>
  

это:

 port=tcp
state=open
name=tor-socks
  

Спасибо

Комментарии:

1. Вы хотите port=tcp или protocol=tcp ?

Ответ №1:

Это проверит наличие ключевых слов, таких как протокол, состояние, имя и печать, пока не появится первый пробел. tr используется для удаления двойных кавычек. Где $ x — это ваша строка.

 echo $x  |grep -oP 'protocol=.*? |state=.*? |name=.*? ' |tr -d '"'
protocol=tcp
state=open
name=tor-socks
  

Приближение-1:

 protocol=$( echo $x  |grep -oP '(?<=protocol=").*?(?=")')
echo $protocol
tcp
  

Аналогично :

 protocol=$( echo $x  |grep -oP '(?<=protocol=").*?(?=")')
state=$(echo $x  |grep -oP '(?<=state=").*?(?=")')
name=$(echo $x  |grep -oP '(?<=name=").*?(?=")')
  

Подход-2:

или просто сделайте eval , чтобы присвоить значения соответствующим переменным. Но я бы не стал этого делать, придерживайтесь первого подхода.

 eval $(echo $x  |grep -oP 'protocol=.*? |state=.*? |name=.*? ')
echo $state
open
  

Комментарии:

1. Спасибо! и у меня есть еще один вопрос. мне нужно получить это в переменной типа $ echo «$protocol», а вывод — «tcp»

2. Спасибо! впервые я вижу практическое использование eval 🙂

3. @JackMagor вы можете принять ответ, отметив его, если это поможет

4. Не делайте этого. Нет абсолютно никаких причин использовать eval для этого, и все обычные причины этого не делают. Также обратите внимание на все переменные без кавычек, которые также являются основным красным флажком.

Ответ №2:

Чтобы удовлетворить требование из вашего комментария, что i need to get this in variable like $ echo "$protocol" and output is "tcp" :

 $ cat tst.sh
declare $(awk -v RS='[[:alpha:]] ="[^"] "' 'RT{print RT}' "$1")
echo "$protocol"
echo "$state"
echo "$name"

$ ./tst.sh file
"tcp"
"open"
"tor-socks"
  

В приведенном выше примере используется GNU awk для RS и RT с несколькими символами, которые, я полагаю, у вас есть, поскольку вы были довольны решением GNU grep.

Ответ №3:

Вы также можете использовать sed для извлечения ваших данных из строки и назначения read отдельной строки переменным :

  echo $line | sed 's/.*protocol="([^"]*)".*state="([^"]*)".*name="([^"]*)".*/1 2 3/' | { read port state name; echo $port $state $name; }
  

Обратите внимание, что переменные port , state , name имеют свое значение внутри блока, заключенного в { и } .