Как использовать sed для извлечения подстроки

у меня есть файл, содержащий следующие строки:

  <parameter name="PortMappingEnabled" access="readWrite" type="xsd:boolean"></parameter>
  <parameter name="PortMappingLeaseDuration" access="readWrite" activeNotify="canDeny" type="xsd:unsignedInt"></parameter>
  <parameter name="RemoteHost" access="readWrite"></parameter>
  <parameter name="ExternalPort" access="readWrite" type="xsd:unsignedInt"></parameter>
  <parameter name="ExternalPortEndRange" access="readWrite" type="xsd:unsignedInt"></parameter>
  <parameter name="InternalPort" access="readWrite" type="xsd:unsignedInt"></parameter>
  <parameter name="PortMappingProtocol" access="readWrite"></parameter>
  <parameter name="InternalClient" access="readWrite"></parameter>
  <parameter name="PortMappingDescription" access="readWrite"></parameter>

Я хочу выполнить команду в этом файле, чтобы извлечь только имена параметров, как показано в следующем выводе:

$sedcommand file.txt
PortMappingEnabled
PortMappingLeaseDuration
RemoteHost
ExternalPort
ExternalPortEndRange
InternalPort
PortMappingProtocol
InternalClient
PortMappingDescription

что это может быть за команда?

5 ответов


вы хотите awk.

Это будет быстрый и грязный хак:

awk -F "\"" '{print }' /tmp/file.txt

PortMappingEnabled
PortMappingLeaseDuration
RemoteHost
ExternalPort
ExternalPortEndRange
InternalPort
PortMappingProtocol
InternalClient
PortMappingDescription

grep родился, чтобы извлекать вещи:

grep -Po 'name="\K[^"]*'

тест с вашими данными:

kent$  echo '<parameter name="PortMappingEnabled" access="readWrite" type="xsd:boolean"></parameter>
  <parameter name="PortMappingLeaseDuration" access="readWrite" activeNotify="canDeny" type="xsd:unsignedInt"></parameter>
  <parameter name="RemoteHost" access="readWrite"></parameter>
  <parameter name="ExternalPort" access="readWrite" type="xsd:unsignedInt"></parameter>
  <parameter name="ExternalPortEndRange" access="readWrite" type="xsd:unsignedInt"></parameter>
  <parameter name="InternalPort" access="readWrite" type="xsd:unsignedInt"></parameter>
  <parameter name="PortMappingProtocol" access="readWrite"></parameter>
  <parameter name="InternalClient" access="readWrite"></parameter>
  <parameter name="PortMappingDescription" access="readWrite"></parameter>
'|grep -Po 'name="\K[^"]*'
PortMappingEnabled
PortMappingLeaseDuration
RemoteHost
ExternalPort
ExternalPortEndRange
InternalPort
PortMappingProtocol
InternalClient
PortMappingDescription

sed 's/[^"]*"\([^"]*\).*//'

делает работу.


вы не должны анализировать XML с помощью таких инструментов, как sed или awk. Он подвержен ошибкам.

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

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

cut -d'"' -f2 < input.txt

Он будет лучше сначала разобрать его и извлечь только имя параметра атрибут:

xpath -q -e //@name input.txt | cut -d'"' -f2

чтобы узнать больше о xpath, см. Этот учебник:http://www.w3schools.com/xpath/


объясняя, как вы можете использовать cut:

cat yourxmlfile | cut -d'"' -f2

он будет "вырезать" все строки в файле на основе " delimiter, и взять 2nd field, что вы и хотели.