Bash读取行并用上一行替换值

时间:2019-01-18 11:02:36

标签: shell awk

我有下面的XML文件,我想用产品ID的值替换其中的值。

我正在使用下面的代码,但是在两行中都替换了相同的产品。

我还在下面提供了示例来源和目标内容。

 while read line
 do
 count=`echo $line | grep "Product ID" | wc -l`
 if [ $count -eq "1" ]
  then
 product=`echo "$line" | grep "Product ID"|awk -F "=" '{print $2}' | awk 
 '{print $1}'`

 name=`grep "$line" -B 1 test.xml | tail -1|sed 's/\///g;s/<Name>//g' | 
  awk '{print $1}'`

 echo $line | sed "s/$name/$product/g" >> data.xml
 else
 echo "$line" >> data.xml
 fi

 done < test.xml

以下是源格式:

 <Products>
<Product ID="ABC1234" UserID="XYX" SUperUserID="ROOT" >
  <Name>1234</Name>  
  <Values>
    <Value AttributeID="A">1</Value>
    <Value AttributeID="B">00</Value>
     </Values>
</Product>
 <Product ID="XYZ1234" UserID="XYX" SUperUserID="ROOT" >
   <Name>1234</Name>
  <Value AttributeID="A">4</Value>
    <Value AttributeID="B">10</Value>
     </Values>
 </Product>

下面将是输出格式:

<Products>
<Product ID="ABC1234" UserID="XYX" SUperUserID="ROOT" >
  <Name>ABC1234</Name>  
  <Values>
    <Value AttributeID="A">1</Value>
    <Value AttributeID="B">00</Value>
     </Values>
</Product>
 <Product ID="XYZ1234" UserID="XYX" SUperUserID="ROOT" >
   <Name>XYZ1234</Name>
  <Value AttributeID="A">4</Value>
    <Value AttributeID="B">10</Value>
     </Values>
 </Product>

请提出其他建议。

2 个答案:

答案 0 :(得分:2)

编辑:如果按照OP的注释,如果某行中的行数超过",那么我将在""之间选择第一个值。

awk -F'[>"<]' '
/Product ID/{
    match($0,/"[^"]*/)
    val=substr($0,RSTART+1,RLENGTH-1)
}
/<Name>/{
    sub(/>.*</,">"val"<")
}
1'  Input_file

运行以上代码后得到的输出如下:

awk -F'[>"<]' '
/Product ID/{
    match($0,/"[^"]*/)
    val=substr($0,RSTART+1,RLENGTH-1)
}
/<Name>/{
    sub(/>.*</,">"val"<")
}
1'  Input_file
 <Products>
<Product ID="ABC1234" UserID="XYX" SUperUserID="ROOT" >
  <Name>ABC1234</Name>  
  <Values>
    <Value AttributeID="A">1</Value>
    <Value AttributeID="B">00</Value>
     </Values>
</Product>
 <Product ID="XYZ1234" UserID="XYX" SUperUserID="ROOT" >
   <Name>XYZ1234</Name>
  <Value AttributeID="A">4</Value>
    <Value AttributeID="B">10</Value>
     </Values>
 </Product>


请您尝试以下。

awk -F'[>"<]' '
/Product ID/{
    match($0,/".*"/)
    val=substr($0,RSTART+1,RLENGTH-2)
}
/<Name>/{
    sub(/>.*</,">"val"<")
}
1' Input_file

答案 1 :(得分:0)

使用Perl单线版

 perl -0777 -pe ' s/(<Product ID=\"(\S+)\".+?<Name>)(.+?)</$1$2</msg '

使用给定的输入

$ cat navku.xml
 <Products>
<Product ID="ABC1234" UserID="XYX" SUperUserID="ROOT" >
  <Name>1234</Name>
  <Values>
    <Value AttributeID="A">1</Value>
    <Value AttributeID="B">00</Value>
     </Values>
</Product>
 <Product ID="XYZ1234" UserID="XYX" SUperUserID="ROOT" >
   <Name>1234</Name>
  <Value AttributeID="A">4</Value>
    <Value AttributeID="B">10</Value>
     </Values>
 </Product>
$ perl -0777 -pe ' s/(<Product ID=\"(\S+)\".+?<Name>)(.+?)</$1$2</msg ' navku.xml
 <Products>
<Product ID="ABC1234" UserID="XYX" SUperUserID="ROOT" >
  <Name>ABC1234</Name>
  <Values>
    <Value AttributeID="A">1</Value>
    <Value AttributeID="B">00</Value>
     </Values>
</Product>
 <Product ID="XYZ1234" UserID="XYX" SUperUserID="ROOT" >
   <Name>XYZ1234</Name>
  <Value AttributeID="A">4</Value>
    <Value AttributeID="B">10</Value>
     </Values>
 </Product>
$