我的意见如下<connection name="test1" transport="tcp"><LPort>host1:11111</hostPort><hostPort>host1:11111</hostPort><abcd> 1234<connection name="test2" transport="tcp"><hostPort>host2:22222</hostPort><GPort>host1:12111</hostPort><connection name="xyz1" transport="tcp"><hostPort>host3:33333</hostPort><FPort>host1:12113</hostPort><efgi> 5678<connection name="xyz2" transport="tcp"><LPort>host1:12234</hostPort><hostPort>host4:4444</hostPort>我希望我的输出如下:test1 host1 1111test2 host2 2222xyz1 host3 3333xyz2 host4 4444把这个拿出来,我就是这么做的,而且很管用。但在我看来,必须有一种更好、更简单的方法来实现它,我没有包括整个逻辑(数组);但是当我有多个在一个文件中搜索,它就会工作。我试图使用&&command组合awk命令,但失败了。下面是我的代码和逻辑的一部分1)我把文件分类2)去掉多余字符,用sed替换为空格3)我获取想要的值并使用awk分配给数组值请注意,我没有包括其余的逻辑(但它工作)简言之,我做了一个while循环,然后将值赋给2或3个数组,并将它们打印在同一行以获得所需的输出cat file  | grep -A5 connection | sed s'/[:="><]/ /g' | awk '/name/ {print $3}'cat file | grep -A5 connection | sed s'/[:="><]/ /g' | awk '/hostPort/ {print $2 " " $3}'如果可能,请提供一个替代解决方案,不涉及使用sed/awk或任何其他方式将搜索条件存储在数组中?如果您可以提供解决方案,请提供每个选项的详细信息;如果您可以的话。谢谢你 最佳答案 必须提醒的是:假设您的输入是格式良好的XML,那么使用XML解析器将提供一个更健壮的解决方案(见底部)。以下是一个实用程序awk解决方案:awk -v RS= -F '<connection name="|<hostPort>' ' { sub(/".*/, "", $2) split($3, tokens, /[:<]/) printf "%-6s %s %s\n", $2, tokens[1], tokens[2] }' file-v RS=告诉awk按段落将输入拆分为记录,其中段落是一段非空行。-F '<connection name="|<hostPort>'通过出现<connection name="或(|)<hostPort>将每个段落拆分为字段,以便感兴趣的数据位于第2和第3个字段的开头($2和$3)。sub(/".*/, "", $2)从字段2中删除第一个"之后的所有内容,实际上只留下连接名。split($3, tokens, /[:<]/)通过出现:和<将第三个字段拆分为一个令牌数组,在第一个数组元素中生成主机名,在第二个数组元素中生成端口。printf "%-6s %s %s\n", $2, tokens[1], tokens[2]打印一个输出行,在连接名中用空格右填充至少6个字符,如在示例输出中所示;如果只想用一个空格分隔输出字段,只需省略-6。可选读取:可在shell脚本中使用的XML解析实用程序(CLIs)xmllint已预先安装在某些平台上:macOS/FreeBSD/PC-BSD(可能是其他BSD变体)一些Linux发行版:Fedora、CentOS在其他服务器上,可以使用一个包;例如,在Ubuntu上:sudo apt-get install libxml2-utils注意:虽然xmllint支持XPath 1.0查询,但它实际上不允许控制输出格式。按需安装替代方案-优于xmllint:xmlstarletxmlstarlet功能强大、灵活,支持多种操作。macOS:使用brew install xmlstarlet通过Homebrew安装Linux:很有可能它可以与您平台的包管理器一起安装;例如,在基于Debian的发行版上,如Ubuntu:sudo apt-get install xmlstarletWindows:从sourceforge手动下载并安装。xidel要求手动download and installation,但其功率和灵活性弥补了这种不便。支持Linux、macOS和Windows下面是与上面列出的3个实用程序进行对比的解决方案。以下格式良好的XML文档假定包含在xidel中—请注意file元素现在是如何包含在单个顶级<connection>元素中的:<doc> <connection name="test1" transport="tcp"> <LPort>host1:11111</LPort> <hostPort>host1:11111</hostPort> <abcd>1234</abcd> </connection> <connection name="test2" transport="tcp"> <hostPort>host2:22222</hostPort> <GPort>host1:12111</GPort> </connection> <connection name="xyz1" transport="tcp"> <hostPort>host3:33333</hostPort> <FPort>host1:12113</FPort> <efgi>5678</efgi> </connection> <connection name="xyz2" transport="tcp"> <LPort>host1:12234</LPort> <hostPort>host4:4444</hostPort> </connection></doc><doc>溶液:xmllint无法控制查询结果的格式需要一个非常重要的xmllinthelper命令:echo 'cat //connection/@name | //hostPort/text()' | xmllint --shell file | awk -F\" ' NR % 2 { next } # skip separator lines NR % 4 == 2 { conn = $2; next } # save connnection name { split($0, tokens, ":") printf "%-6s %s %s\n", conn, tokens[1], tokens[2] }'awk溶液:xmlstarlet xmlstarlet子命令通过将选项翻译成场景后的XLST模板来支持非常灵活的提取:xmlstarlet sel -t -m '//connection' -v 'str:align(@name, " ")' \ -o ' ' \ -c 'str:replace(hostPort, ":", " ")' -n filesel溶液:xidel非常灵活,不仅支持XML,而且支持HTML和JSON。虽然它不支持XLST,但它支持XQuery,这是一个具有类似XSLT特性的XPath超集,它支持强大的转换。据我所知,没有填充功能,但是,使用一个-直接-辅助命令:xidel file -q --xquery \ 'for $c in //connection return concat($c/@name, " ", replace($c/hostPort, ":", " "))' | awk '{ printf "%-6s %s %s\n", $1, $2, $3 }'也就是说,XQuery甚至支持用户定义的函数,因此您可以编写自己的填充函数:xidel -q file --xquery ' declare function pad($s as xs:string?) as xs:string { substring(concat($s, " "), 1, 6) } for $c in //connection return concat(pad($c/@name), " ", replace($c/hostPort, ":", " "))'关于arrays - 结合awk命令将搜索的输出显示在一行中,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/44213565/
10-09 12:44