使用sed迭代文件并用新值替换旧值

时间:2015-05-20 07:47:22

标签: bash shell unix sed scripting

我试着编写一个脚本,其中while循环逐行读取文件,对该行上的两个值执行命令(获取两个新值),然后用两个新值替换两个旧值,然后转到下一行。

例如,txt文件example.txt包含以下数据:

 1432771200 != 1432800000 OPTION VALUE
 1432771200 != 1432800210 OPTION VALUE
 1432771200 != 1432800033 OPTION VALUE

我运行以下脚本:

 #!/bin/bash -x
 #
    while read line
    do
            arr=($line)
            CURRENTDATE=`h2e ${arr[0]}`
            PROPOSEDDATE=`h2e ${arr[2]}`
            echo $CURRENTDATE
            echo $PROPOSEDDATE
    #       echo $line |
            sed -i "s/${arr[0]}/$CURRENTDATE/"
    #       echo $line |
            sed -i "s/${arr[2]}/$PROPOSEDDATE/"
    done < /srg/pro/data/example.txt

我期望在example.txt文件中看到的是替换每一行的第一个和第三个值..所以它应该如下所示:

 Thu May 28 01:00:00.000 2015 BST != Thu May 28 09:00:00.000 2015 BST OPTION VALUE
 Thu May 28 01:00:00.000 2015 BST != Wed May 27 01:00:00.000 2015 BST OPTION VALUE
 Fri May 28 01:00:00.000 2015 BST != Fri May 29 06:00:00.000 2015 BST OPTION VALUE

等等......

当我使用bash -x Interface.sh运行shell脚本时,我得到了这个:

 read line
 + arr=($line)
 ++ h2e 1432771200
 + CURRENTDATE='1432771200.000  2015148  Thu May 28 01:00:00.000 2015 BST (1)'
 ++ h2e 1432800000
 + PROPOSEDDATE='1432800000.000  2015148  Thu May 28 09:00:00.000 2015 BST (1)'
  + echo 1432771200.000 2015148 Thu May 28 01:00:00.000 2015 BST '(1)'
   1432771200.000 2015148 Thu May 28 01:00:00.000 2015 BST (1)
   + echo 1432800000.000 2015148 Thu May 28 09:00:00.000 2015 BST '(1)'
   1432800000.000 2015148 Thu May 28 09:00:00.000 2015 BST (1)
 + sed -i 's/1432771200/1432771200.000  2015148  Thu May 28 01:00:00.000       2015 BST (1)/'
 sed: no input files
 + sed -i 's/1432800000/1432800000.000  2015148  Thu May 28 09:00:00.000   2015 BST (1)/'
 sed: no input files
 + read line
 + arr=($line)
 ++ h2e 1432771200
 + CURRENTDATE='1432771200.000  2015148  Thu May 28 01:00:00.000 2015 BST (1)'
 ++ h2e 1432800000
+ PROPOSEDDATE='1432800000.000  2015148  Thu May 28 09:00:00.000 2015 BST  (1)'
 + echo 1432771200.000 2015148 Thu May 28 01:00:00.000 2015 BST '(1)'
 1432771200.000 2015148 Thu May 28 01:00:00.000 2015 BST (1)
 + echo 1432800000.000 2015148 Thu May 28 09:00:00.000 2015 BST '(1)'
 1432800000.000 2015148 Thu May 28 09:00:00.000 2015 BST (1)
 + sed -i 's/1432771200/1432771200.000  2015148  Thu May 28 01:00:00.000 2015 BST (1)/'
 sed: no input files
+ sed -i 's/1432800000/1432800000.000  2015148  Thu May 28 09:00:00.000 2015 BST (1)/'
sed: no input files 

请帮忙!不知道如何解决这个问题!

2 个答案:

答案 0 :(得分:0)

使用您的批次(还有其他方式)

#!/bin/bash -x
 #
  cp /srg/pro/data/example.txt /tmp/temp.file

  cat /srg/pro/data/example.txt \
  | while read line
    do
            arr=($line)
            CURRENTDATE=`h2e ${arr[0]}`
            PROPOSEDDATE=`h2e ${arr[2]}`
            echo $CURRENTDATE
            echo $PROPOSEDDATE
    #       echo $line |
            sed -i "s/${arr[0]}\(.*\)${arr[2]}/${CURRENTDATE}\1${PROPOSEDDATE}/" /tmp/temp.file
    done

mv /tmp/temp.file /srg/pro/data/example.txt 
  • sed -i无法正常使用,需要文件
  • 我使用临时文件来避免读取在循环内修改的同一文件的问题,这通常会产生意外结果(如空文件)
  • 这项工作适用于您的样本,但它取决于您的数组的行结构和数据文件的实际结构中的sed替换

答案 1 :(得分:0)

read命令可以读取将行拆分为字段:

outfile=/tmp/some_tmp_file_you_will_move
while read date1 marker date2 otherfields; do
    CURRENTDATE=`h2e ${date1}`
    PROPOSEDDATE=`h2e ${date2}`
    echo $CURRENTDATE
    echo $PROPOSEDDATE
    echo "${CURRENTDATE} ${marker} ${PROPOSEDDATE} ${otherfields}" >> ${outfile}
done < /srg/pro/data/example.txt

当您不需要在循环中看到CURRENTDATE / PROPOSEDDATE时,您可以将输出重定向到循环外部以获得更好的性能:

outfile=/tmp/some_tmp_file_you_will_move
while read date1 marker date2 otherfields; do
    CURRENTDATE=`h2e ${date1}`
    PROPOSEDDATE=`h2e ${date2}`
    echo "${CURRENTDATE} ${marker} ${PROPOSEDDATE} ${otherfields}"
done < /srg/pro/data/example.txt > ${outfile}

注意:考虑使用$(h2e ...)而不是``