脚本:
#!/bin/ksh
tu=$(cat /export/home/a1016169/stack.txt;)
tu1=$(echo "$tu" | awk '/EM_CLIENT_VERSION/{x=NR+17}(NR<=x){print}' | awk '/tu/{x=NR+1}(NR<=x){getline; print}' | awk -F= '{print $(NR+2)}' | perl -lne 'print substr($_,19,5)';)
print "\n $tu1"
qc=$(cat /export/home/a1016169/stack.txt;)
qc1=$(echo "$qc" | awk '/EM_CLIENT_VERSION/{x=NR+17}(NR<=x){print}' | awk '/qc/{x=NR+1}(NR<=x){getline; print}' | awk -F= '{print $(NR+2)}' | perl -lne 'print substr($_,19,5)';)
print "\n $qc1"
sed 's/"$qc1"/"$tu1"/' - > /export/home/a1016169/stack.txt
stack.txt
文件:
<prpr name = "EM_CLIENT_VERSION" encryptionClass = "com.hewitt.cat.tba.properties.encrypter.NoOpPropertyEncrypter">
<lcycl name="pu">
<prprvl bgdt="2000.01.01 00:00" endt="3000.01.01 00:00">9999a</prprvl>
</lcycl>
<lcycl name="qc">
<prprvl bgdt="2000.01.01 00:00" endt="3000.01.01 00:00">9999a</prprvl>
</lcycl>
<lcycl name="qa">
<prprvl bgdt="2000.01.01 00:00" endt="3000.01.01 00:00">9999b</prprvl>
</lcycl>
<lcycl name="tu">
<prprvl bgdt="2000.01.01 00:00" endt="3000.01.01 00:00">0220a</prprvl>
</lcycl>
<lcycl name="dv">
<prprvl bgdt="2000.01.01 00:00" endt="3000.01.01 00:00"></prprvl>
</lcycl>
</prpr>
我从最后一个命令中收到一个错误,为Can't open -
。
我想更改9999a
(<lcycl name="qc">
仅在本节下)为0220a
值。该值应取自<lcycl name="tu">
.
答案1
使用XML小星:
$ xmlstarlet ed -u '//lcycl[@name="qc"]/prprvl' -v 0220a file.xml
<?xml version="1.0"?>
<prpr name="EM_CLIENT_VERSION" encryptionClass="com.hewitt.cat.tba.properties.encrypter.NoOpPropertyEncrypter">
<lcycl name="pu">
<prprvl bgdt="2000.01.01 00:00" endt="3000.01.01 00:00">9999a</prprvl>
</lcycl>
<lcycl name="qc">
<prprvl bgdt="2000.01.01 00:00" endt="3000.01.01 00:00">0220a</prprvl>
</lcycl>
<lcycl name="qa">
<prprvl bgdt="2000.01.01 00:00" endt="3000.01.01 00:00">9999b</prprvl>
</lcycl>
<lcycl name="tu">
<prprvl bgdt="2000.01.01 00:00" endt="3000.01.01 00:00">0220a</prprvl>
</lcycl>
<lcycl name="dv">
<prprvl bgdt="2000.01.01 00:00" endt="3000.01.01 00:00"/>
</lcycl>
</prpr>
XPath//lcycl[@name="qc"]/prprvl
将匹配作为具有 value 属性的节点prprvl
的直接子节点的节点。在这里,无论节点的初始值是什么,都会将其值更改为。lcycl
name
qc
xmlstarlet
prprvl
0220a
如果您不想对0220a
值进行硬编码,而是从节点中选取它//lcycl[@name="tu"]/prprvl
,请使用
xmlstarlet ed -u '//lcycl[@name="qc"]/prprvl' \
-x '//lcycl[@name="tu"]/prprvl/text()' file.xml
将输出重定向到新文件,然后将新文件重命名为原始名称。
file.xml
Perl 中的等效内容,将从当前目录中获取:
#!/usr/bin/perl
use strict;
use warnings;
use XML::XPath;
use XML::XPath::XMLParser;
my $xp = XML::XPath->new( filename => 'file.xml' );
$xp->setNodeText( '//lcycl[@name="qc"]/prprvl', '0220a' );
my $nodeset = $xp->find('/');
foreach my $node ( $nodeset->get_nodelist() ) {
print XML::XPath::XMLParser::as_string($node);
}
在这里,如果您想从其他节点选择该值,请使用
$xp->setNodeText( '//lcycl[@name="qc"]/prprvl',
$xp->getNodeText('//lcycl[@name="tu"]/prprvl') );
而不是另一条setNodeText()
线。
将输出重定向到新文件,然后将新文件重命名为原始名称。
您收到的错误是由于尝试打开名为-
. GNUsed
会将其-
视为标准输入流,但其他sed
实现(例如 BSD sed
)会将其视为普通文件名。
无论如何,您都不会提供sed
任何可操作的数据。这意味着您重定向到的文件将被截断并留空。