如何使用sed提取子字符串

MOH*_*MED 48 linux shell ubuntu sed xml-parsing

我有一个包含以下行的文件:

  <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>
Run Code Online (Sandbox Code Playgroud)

我想在此文件上执行命令以仅提取以下输出中显示的参数名称:

$sedcommand file.txt
PortMappingEnabled
PortMappingLeaseDuration
RemoteHost
ExternalPort
ExternalPortEndRange
InternalPort
PortMappingProtocol
InternalClient
PortMappingDescription
Run Code Online (Sandbox Code Playgroud)

这个命令可能是什么?

Ken*_*ent 85

grep诞生于提取事物:

grep -Po 'name="\K[^"]*'
Run Code Online (Sandbox Code Playgroud)

测试您的数据:

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
Run Code Online (Sandbox Code Playgroud)

  • 仅供参考,关于`-P`的grep联机帮助页:"这是高度实验性的,**grep -P**可能会警告未实现的功能." (7认同)
  • 我不得不查找`\ K`:它保留了匹配之外的东西(所以你没有得到`name ="PortMappingLeaseDuration"`.[进一步阅读](http://www.regular-expressions.信息/ refadv.html) (5认同)
  • 或者,您也可以使用 grep 两次: `grep -o 'name="[^"]*' | grep -o '[^"]*$'`。它产生相同的结果。 (5认同)
  • 对于那些不想使用-P标志的人;没有任何默认grep支持的扩展正则表达式可以执行`\ K`的操作,但是您可以简单地通过sed将其通过管道传送:`grep -o'name =“ [^”] * | sed's / name =“ // g'` (2认同)

unx*_*nut 57

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

做的工作.

  • 这既不简单也不优雅.只是神秘莫测. (49认同)
  • 感谢您回答问题,而不是提出不同的工具! (24认同)
  • @Stefan,也许是未经训练的眼睛.但是花时间与RegEx和爵士乐或毕加索一样,你会欣赏到简单的美. (21认同)
  • 虽然它可以完成这项工作,但如果您真正解释正在发生的事情将是有益的. (8认同)
  • 这就是神秘的意思:对未经训练的眼睛完全不可读. (3认同)
  • ITT:一代人在成长过程中没有像正则表达式那样学习强大的基础知识!*叹气*授予,awk,grep,perl,sed,lex,yacc,javascript都使用稍微不同的变化(感谢posix!),但仍然是一个非常强大的编程概念.我对一些答案的复杂性感到震惊. (2认同)
  • 神秘但非常强大。值得花时间学习正则表达式,相信我。 (2认同)

Chr*_*ris 35

你想要的awk.

这将是一个快速而肮脏的黑客:

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

PortMappingEnabled
PortMappingLeaseDuration
RemoteHost
ExternalPort
ExternalPortEndRange
InternalPort
PortMappingProtocol
InternalClient
PortMappingDescription
Run Code Online (Sandbox Code Playgroud)

  • `cut`可以更快地完成工作:-) (2认同)

Mic*_*jer 16

您不应该使用sed或awk等工具解析XML.这很容易出错.

如果输入更改,并且在name参数之前,您将获得换行符而不是空格,它将在某一天失败,从而产生意外结果.

如果您确定,您的输入将始终以这种方式格式化,您可以使用cut.它的速度比sedawk:

cut -d'"' -f2 < input.txt
Run Code Online (Sandbox Code Playgroud)

最好先解析它,并仅提取参数名称属性:

xpath -q -e //@name input.txt | cut -d'"' -f2
Run Code Online (Sandbox Code Playgroud)

要了解有关xpath的更多信息,请参阅本教程:http://www.w3schools.com/xpath/


Rus*_*wal 5

说明如何使用cut

cat yourxmlfile | cut -d'"' -f2

它将“剪切”根据文件中的所有行 d elimiter,并且将采取2˚F ield,这是你想要的。