【问题标题】:Set XML tags through shell script通过 shell 脚本设置 XML 标签
【发布时间】:2012-11-11 00:40:01
【问题描述】:

您好,我一直在使用 shell 脚本设置 XML 的标记值(值可能包含特殊字符)。

XML 标记值应该用双引号括起来。

要求: 我有一个带有标签值的 xml。对于 shell 脚本,我必须放置一个带有值的新 XML 标签 标签之前。 所以我正在使用 sed,我尝试如下。如果 $4 $5 没有特殊字符,这可以正常工作。如何使用特殊字符进行此操作?(例如:&><:>

sed '/<jobResulsDir/s/<jobResulsDir/<CommCellUser userName="'$4'" password="'$5'" >  <\/CommCellUser> '$test' <jobResulsDir  /' $temp_dir/PreImageModeFile.xml > $temp_dir/PreImageModeFile2.xml

除了sed还有其他方法吗。请帮帮我

【问题讨论】:

  • 抱歉,我认为没有粘贴完整的 sed 命令:sed '/ '$test' $temp_dir/PreImageModeFile2.xml
  • 你必须告诉 SO 它是代码。

标签: xml shell unix xml-parsing sed


【解决方案1】:

为什么不使用 perl?它必须是一个shell脚本吗?

   #!/usr/bin/perl
   use XML::Simple;
   use Data::Dumper;
   open(my $XML_IN, '<', '/xml/file/path.xml');
   $/=undef;
   my $xml_ref = XMLIn(<$XML_IN>);
   print Dumper \$xml_ref;
   # ... access $xml_ref in appropriate location, adding element / value
   my $new_xml = XMLout($xml_ref);
   close $XML_IN;
   open(my $XML_OUT, '>', '/xml/file/path.xml');
   print $XML_OUT $new_xml;
   close $XML_OUT;

【讨论】:

  • 是的,我必须使用 shell 脚本
【解决方案2】:

你试图用 sed 做的事情会破坏你的大脑,你必须在每个特殊字符之前使用反斜杠才能让它工作。我使用 m4 来完成这种工作。看一个例子:

define(your_macro_name,<Delete>
<Object fdn="SubNetwork=somemoredata`,SubNetwork=somedata'`,ManagedElement'=$1"/>
</Delete>)dnl

将上述代码保存在名为“xmlmacros.m4”的文件中 然后创建一个名为“test.m4”的文件并添加以下内容:

include(xmlmacros.m4)dnl
your_macro_name(YOURXMLVALUE)

如果这两个文件在同一个文件夹中,您可以运行m4 test.m4,您的输出将是:

 <Delete>
 <Object fdn="SubNetwork=somemoredata,SubNetwork=somedata,ManagedElement=YOURXMLVALUE"/>

其中$1 将替换为“test.m4”文件括号中的值。您还可以添加更多定义,以按需创建 xml 文件,例如 xml 标头等。

以上是您可以使用的工作示例。您可以四处寻找有关 m4 的更多信息,我总是将它用于此类工作。

【讨论】:

  • 我也未能正确粘贴内容:在我给定的示例中,命令输出将以结束 XML 标记结尾:''
【解决方案3】:

Awk 不关心“特殊字符”。这在 sed 中:

sed '/<jobResulsDir/s/<jobResulsDir/<CommCellUser userName="'$4'" password="'$5'" > <\/CommCellUser> '$test' <jobResulsDir /'

这是在 awk 中吗:

awk -v userName="$4" -v password="$5" -v test="$test" '
   /<jobResulsDir/{ sub(/<jobResulsDir/, "<CommCellUser userName=" userName " password=" password " </CommCellUser> " test " <jobResulsDir ") }
   { print }
'

但您实际上不需要预先测试/&lt;jobResulsDir/,因为 sub() 仅在 RE 存在时才会出现,因此您可以将其缩写为:

awk -v userName="$4" -v password="$5" -v test="$test" '
   { sub(/<jobResulsDir/, "<CommCellUser userName=" userName " password=" password " </CommCellUser> " test " <jobResulsDir "); print }
'

不确定这是否是您的评论/问题所要求的,但如果您需要在值名称周围加上双引号,只需调整脚本以在您需要的位置提供它们:

awk -v userName="$4" -v password="$5" -v test="$test" '
   { sub(/<jobResulsDir/, "<CommCellUser userName=\"" userName "\" password=\"" password "\" </CommCellUser> \"" test "\" <jobResulsDir "); print }
'

最后,如果您愿意,可以通过以下一种方式拆分工作,使其更具可读性和效率:

awk -v userName="$4" -v password="$5" -v test="$test" '
   BEGIN{
      q = "\""
      rep = \
         "<CommCellUser userName=" q userName q\
         " password="              q password q\
         " </CommCellUser> "       q test     q\
         " <jobResulsDir "
   }
   { sub(/<jobResulsDir/, rep); print }
'

看着它以这种方式布局,我意识到我对 awk 不关心“特殊字符”有点撒谎。 sub() 实际上确实关心 1 个“特殊字符”,即替换字符串中的“&”,因为它用于反向引用 sub() 中匹配的内容,因此您需要将“&”替换为“\&”代表:

awk -v userName="$4" -v password="$5" -v test="$test" '
   BEGIN{
      q = "\""
      rep = \
         "<CommCellUser userName=" q userName q\
         " password="              q password q\
         " </CommCellUser> "       q test     q\
         " <jobResulsDir "
   }
   { gsub(/&/,"\\\\&",rep); sub(/<jobResulsDir/, rep); print }

它需要 4 个 "\",因为字符串文字在 awk 中会被解释两次(一次是在解释脚本时,另一次是在执行脚本时),所以你需要 \\ 来代替 \ 来获得文字反斜杠。

如果您愿意,还有一种使用 match() 和 substr() 的替代方法,它没有该约束:

awk -v userName="$4" -v password="$5" -v test="$test" '
   BEGIN{
      q = "\""
      rep = \
         "<CommCellUser userName=" q userName q\
         " password="              q password q\
         " </CommCellUser> "       q test     q\
         " <jobResulsDir "
   }
   match($0,/<jobResulsDir/) {
       $0 = substr($0,1,RSTART) rep substr($0,RSTART+RLENGTH)
   }
   { print }
'

就我个人而言,我会使用 match()/substr() 方法,因为我讨厌搞乱转义字符。

只是循环回到我们开始的地方,如果你愿意,可以按照以下方式将其写成单行:

awk -v userName="$4" -v password="$5" -v test="$test" '{
   print (match($0,/<jobResulsDir/) ? substr($0,1,RSTART) "<CommCellUser userName=\"" userName "\"password=\"" password "\" </CommCellUser> \"" test "\" <jobResulsDir " substr($0,RSTART+RLENGTH) : $0)
}'

【讨论】:

  • 谢谢它的工作正常 :) :) 。即使我被困在获得相同的 stetted 值。假设现在设置了用户名和密码。如果我必须读取 xml 文件并取回双引号中的值,我该怎么做?(值包含特殊字符)
  • 对不起,我不知道你在问什么。请更新您的原始帖子,以使用一些小示例输入(包括 wget 命令的输出)和预期输出来说明您的新问题,或者更好地发布新问题,因为您的原始问题现已解决。
  • 我更新了我的答案,以防您只是要求在所有变量的值周围加上双引号。
  • awk 还存在一个问题。如果 $4 或 $5 包含 & 然后它的值中的 & 替换为 的形式出现
  • 该死的你已经发现了:-)!。当您输入时,我正在更新我的答案,见上文。
猜你喜欢
  • 2012-11-11
  • 1970-01-01
  • 2018-11-16
  • 2016-07-15
  • 2016-12-23
  • 1970-01-01
  • 2010-12-13
  • 2012-08-29
  • 1970-01-01
相关资源
最近更新 更多