在UNIX Shell脚本中删除XML标记之间的新行

时间:2019-06-11 07:39:37

标签: xml bash shell unix formatting

<mstr>
  <srt>Payment towards File# 1234</srt>
  <msg>info for treat sxc
  Pay to shankar  A/C#999999
  bank of ooty</msg>
  <ins>info for party BB
   Pay to kumar A/C#999999
   state bank</ins>
</mstr>

上面的XML我想像下面那样转换,这意味着数据包装在开始和结束标记之间的下一行中。应该在下面这样的一行中。

 <mstr>
  <srt>Payment towards File# 1234</srt>
  <msg>info for treat sxc Pay to shankar  A/C#999999 bank of chen</msg>
  <ins>info for party BB Pay to kumar A/C#999999 state bank</ins>
</mstr>

我通过参考网络答案尝试了以下方法。想了解awk命令下面的内容是否还在寻找其他替代方法来解决我的问题?

 awk '{printf /^</&&!/^<\//?RS $0:$0}'

5 个答案:

答案 0 :(得分:2)

尽管可以肯定有更好的选择,但我建议在PYX format文件上使用awk。 PYX格式是从SGML ESIS格式派生的XML文档的行式表示。 (请参阅ESIS-ISO 8879元素结构信息集规范,ISO / IEC JTC1 / SC18 / WG8 N931(ESIS))。

PYX格式非常易于描述和理解。每行的第一个字符标识该行的内容类型。内容不会直接跨越行,尽管连续的行可能包含相同的内容类型。对于标记属性,属性名称和值仅用空格分隔,而无需使用额外的引号。前缀字符为:

( start-tag
) end-tag
A attribute
- character data (content)
? processing instruction

因此我们可以要求xmlstarlet将XML转换为PYX,使用awk删除行,然后将其转换回XML文件:

$ xmlstarlet pyx file.xml | sed -E '/^-\\n/b;/^-/s/\\n +/ /g' | xmlstarlet p2x -

答案 1 :(得分:1)

以下是awk脚本的说明。

awk '{printf /^</&&!/^<\//?RS $0:$0}'

希望屏幕图像清晰。

enter image description here

答案 2 :(得分:0)

使用XML感知工具处理XML,使用net use O: /delete net use O: %1 /persisten:no echo %PATH% IF EXIST "C:\Program Files (x86)\SmartBear\TestExecute 12" ( **I would like to enter conversion of project here** "C:\Program Files (x86)\SmartBear\TestExecute 12\Bin\TestExecute.exe" "O:\Diamond.pjs" ) ELSE ( echo "test execute 12 not installed" ) net use O: /delete sed可能会轻易破坏数据。

例如,在我碰巧维护的工具xsh中,它实际上是XML::LibXML的包装器,您可以执行以下操作:

awk

输出几乎是预期的-它只保留“ ooty”而不是“ chen”,但是可以通过添加轻松地解决

open file.xml ;
for /mstr/* set . normalize-space(.) ;
save :b ;

答案 3 :(得分:0)

您想要做的-在文本的开头和结尾处删除空格字符,并将空格和换行符的任何序列折叠为文本中的单个空格字符-被称为空白规范化 XML,并且可以通过许多现成的XML处理工具来完成,而无需临时的shell脚本。例如,您可以按照以下方式使用tidy(可在http://tidy.sourceforge.net/上使用,并且可能已经安装在您的计算机上,或者可以通过Debian / Ubuntu上的sudo apt-get install tidy安装)对输入进行空白规范化(假定存储在test.xml中)

tidy -xml -w 80 test.xml

awk单行打印任何输入行($0),省略换行符(通过使用printf()而不是print()),并加上RS(记录分隔符,如果该行以看起来像开始元素标签(/</)开头但看起来不像结束元素标签(!/^<\//)开头,则默认在输出行之前插入制表符。这两个正则表达式测试与&&逻辑和运算符结合在一起,并且是条件表达式的一部分,其中?字符之前的所有内容均为测试条件,而?之后的部分则表示“ “ if”和“ else”分支分别取决于条件,以:分隔。对于您的输入,awk程序将在一行上输出所有内容(不终止换行符),并在每个start-element标记之前加一个制表符。它将无法用空格字符分隔连续的文本行,并且错误地将整个输入行作为第一个参数传递给printf(),以使输入文本中的百分比字符在printf中被解释为placholder格式化字符串,会破坏您的输出。

帮个忙,并使用真实的XML或SGML工具来处理标记。

答案 4 :(得分:0)

我将使用带有XML解析模块的脚本语言。例如,使用ruby:

ruby -r'rexml/document' -e '
    file = ARGV.shift
    doc = REXML::Document.new(File.new(file))
    doc.elements.each("/mstr/*") {|child| child.text = child.text.gsub(/\n\s*/, " ")}
    File.open(file, "w") {|f| f.puts(doc.to_s)}
' file.xml

产生文件

<mstr>
  <srt>Payment towards File# 1234</srt>
  <msg>info for treat sxc Pay to shankar  A/C#999999 bank of ooty</msg>
  <ins>info for party BB Pay to kumar A/C#999999 state bank</ins>
</mstr>