只需要将 xml 文件的某些行连接在一起

只需要将 xml 文件的某些行连接在一起

我想将此 XML 转换为仅肯定线连接在一起。这样我以后就可以只 grep 特定的行。如果此 XML 使用属性,则数据将已经在 1 行中。我不想使用任何 XSLT 来执行此操作。 grep、sed、awk、xmlstarlet、xpath 会很棒

因此,如果一行包含"<instruction>",那么我需要抓取接下来的 4 行并将它们全部放在一行中。没有逗号。如下所示。

这不像发布的问题这里:具有开始“加入”序列的日期的设定模式。

awk '
    /\<instruction\>/ && line {print line; line=""}
    {line = line ? line" "$0 : $0}
    END {print line}
'

这将行折叠到结束标记,但没有引入结束标记行本身。

平台将在Windows 2012R2服务器上。将安装 Gnu utils。文件大小约为 100k。

                        <instruction>
                          <name>AAAAA</name>
                          <value>WHITE</value>
                          <type>0</type>
                        </instruction>
                        <instruction>
                          <name>BBBBB</name>
                          <value>WHITE</value>
                          <type>0</type>
                        </instruction>
                        <instruction>
                          <name>CCCCC</name>
                          <value>WHITE</value>
                          <type>0</type>
                        </instruction>
                      <routing/>
                      <phantom>False</phantom>
                      <AssemblyHistory/>

所需输出:(可能已换行,但指令元素应全部位于 1 行中)

<instruction><name>AAAAA</name><value>WHITE</value><type>0</type></instruction> <instruction><name>BBBBB</name><value>WHITE</value><type>0</type></instruction> <instruction><name>CCCCC</name><value>WHITE</value><type>0</type></instruction> <routing/> <phantom>False</phantom> <AssemblyHistory/>

类似示例(格式不正确的 XML)

data line 2
cust:
tommy
smith
123 main
endcust
data line 16
TRACE: error at xy123
cust:
mary 
smith
444 broadway
endcust
LOG: logon tty3
LOG: free memory before gc 33453211
root: ps -ealf  tty0 


data line 2
cust: tommy smith123 main endcust
data line 16
TRACE: error at xy123
cust:mary smith444 broadway endcust
LOG: logon tty3
LOG: free memory before gc 33453211
root: ps -ealf  tty0 

将整个文件复制到标准输出,不省略任何行。当您找到“cust:”时,可以:1) JOIN 接下来的 4 行或 2) JOIN 行,直到找到“endcust”

是同样的事情,但是这次您不能使用 XML 工具。那么如果遇到这种情况,你会如何解决呢?如果最上面的问题是 XML,那么很好。如果没有,请使用第二个示例

答案1

您可以使用 sed 的范围运算符来解决您的情况,但在此之前请确保处理同一行上的标记和反标记。同一行上的多个标签也不会被处理。

sed -e '
    s/^[[:blank:]]*//
    \|<instruction>.*</instruction>|b
    \|<instruction>|,\|</instruction>|!b
    H;\|</instruction>|!d
    s/.*//;x;s/\n[[:blank:]]*//g;s/^\n//
' input_xml_lookalike_file

答案2

我猜你想使用 grep/sed/awk 的原因是因为你熟悉它们。但这并不能使它们成为完成这项工作的正确工具。仅仅因为您知道如何使用螺丝刀就使用螺丝刀来钉钉子并不是一个聪明的主意。

您需要 XML 感知工具来实现这一点:XSLT 或 XQuery。(首先,是什么让您认为标签<instruction>永远不会包含任何空格?并且指令元素的内容将始终分布在 4 行上?)

StackOverflow 上有很多用户询问如何生成以特定方式格式化的 XML,这限制了他们对 XML 工具的选择。当我们问他们为什么需要这样做时,答案总是有人使用 awk、grep 或 Perl 等不支持 XML 的工具编写了一个应用程序来读取 XML。如果这样做,您就失去了 XML 的全部意义(以及它带来的所有互操作性优势)。

答案3

value例如,提取每个节点的子节点的值,instruction该节点也有一个其值正在使用的name子节点Exterior ColorXML小星:

xmlstarlet sel -v '//instruction[name = "Exterior Color"]/value' -nl file.xml

给定文件

<?xml version="1.0"?>
<AssemblyHistory>
  <routing>
    <instruction>
      <name>Interior Finish</name>
      <value>WHITE</value>
      <type>0</type>
    </instruction>
    <instruction>
      <name>Exterior Color</name>
      <value>WHITE</value>
      <type>0</type>
    </instruction>
    <instruction>
      <name>Base Vinyl Color</name>
      <value>WHITE</value>
      <type>0</type>
    </instruction>
  </routing>
  <phantom>False</phantom>
</AssemblyHistory>

这将返回字符串WHITE

以下将返回与所有节点中的值name相对应的每个:WHITEinstruction

xmlstarlet sel -t -v '//instruction[value = "WHITE"]/name' -nl  file.xml

答案4

这几乎有效:

awk 'BEGIN {RS="<instruction>"; FS="\n"; OFS=""} NR>1 {$1=RS; NF--; print}'

但它会跳过前面的行,并且在看到 /instruction 标签时不会停止加入

input:
LINE 0
LINE 1
LINE 2
<instruction>
<name>Glass SQFT</name>
<value>7.02</value>
<type>0</type>
</instruction>
LINE 3

output:
<instruction><name>Glass SQFT</name><value>7.02</value><type>0</type></instruction>LINE 3

相关内容