使用bash脚本修改文件

时间:2015-03-19 20:11:00

标签: bash awk sed

我正在尝试编写一个脚本,对文件中的下方文本执行某些操作,说myfile.txt

<MY_TEXT="XYZ" PATH="MNO"
<location= "XYZ" path="ABC" 
\location>
<R_DATA = MNOP
 <Mylocation ="ghdf" stime=20150301 etime=20150401 >
 <Mylocation ="ghdf" stime=20150401 etime=20150501 >
\R_DATA>
<Blah>
\MY_TEXT>

<MY_TEXT="ABC" PATH="EFG"
<location= "QQQ" path="LLL" 
\location>
<R_DATA = MNOP
 <Mylocation ="ghdf" stime=20150301 etime=20150401 >
 <Mylocation ="ghdf" stime=20150401 etime=20150501 >
\R_DATA>
<Blah>
\MY_TEXT>

在这里,我看到我有一行<MY_TEXT="XYZ",然后在这场比赛中,我尝试更改位于<MY_TEXT \MY_TEXT>之间的行。我需要对行<Mylocation行进行更改并修改etime=20150401,然后在其后添加一个新行。现在所有这些都需要在我已经传递的文件中完成,或者创建一个具有上述修改的新文件。我正在寻找一种方法,通过阅读单独的线条和跟踪线条使其变得复杂。

3 个答案:

答案 0 :(得分:1)

您可以通过sed

通过两个命令执行此操作
sed -e '/MY_TEXT="XYZ"/,/MY_TEXT/!d' data.dat

这会看到正确的MY_TEXT块。将替换正确的etime值的部分可以按如下方式完成

sed 's/etime=20150401/etime=$newtime/g'

您可以将这两个语句组合在一个命令中,如下所示:

sed -e '/MY_TEXT="XYZ"/,/MY_TEXT/!d;s/etime=20150401/etime=$newtime/g' data.dat

如果您希望将更改应用于同一文件,则可以使用sed的{​​{1}}就地操作标记

答案 1 :(得分:1)

from=20150401   # value to match
to=20150402     # new value

sed '
    # For lines between the two markers
    /<MY_TEXT/,/\\MY_TEXT/ {
        # only for lines matching "Mylocation"
        /Mylocation/ {
            # change the "etime" value
            s/etime='"$from"'/etime='"$to"'/
            # add a newline at the beginning of the line
            ta  # ONLY if a replacement was made, goto a
            bb  # goto b
            :a
            # insert a blank line
            i
            :b
        }
    }
' file

输出

<MY_TEXT="XYZ" PATH="MNO"
<location= "XYZ" path="ABC" 
\location>
<R_DATA = MNOP

 <Mylocation ="ghdf" stime=20150301 etime=20150402 >
 <Mylocation ="ghdf" stime=20150401 etime=20150501 >
\R_DATA>
<Blah>
\MY_TEXT>

<MY_TEXT="ABC" PATH="EFG"
<location= "QQQ" path="LLL" 
\location>
<R_DATA = MNOP

 <Mylocation ="ghdf" stime=20150301 etime=20150402 >
 <Mylocation ="ghdf" stime=20150401 etime=20150501 >
\R_DATA>
<Blah>
\MY_TEXT>

太糟糕了,您的数据实际上并不是XML。那么会有更强大的方法。

答案 2 :(得分:1)

你说你想修改你的目标区块中包含<Mylocation的行,但是你没有说你希望它们被改成什么,所以我选择将你的行改为“这里是蓬松的兔子“:

$ cat tst.awk         
BEGIN { RS=""; ORS="\n\n" }
/^<MY_TEXT="XYZ"/ {
    gsub(/<Mylocation[^\n]*\n/,"here is a fluffy bunny\nand an added line after it\n")
}
{ print }

$ awk -f tst.awk file
<MY_TEXT="XYZ" PATH="MNO"
<location= "XYZ" path="ABC" 
\location>
<R_DATA = MNOP
 here is a fluffy bunny
and an added line after it
 here is a fluffy bunny
and an added line after it
\R_DATA>
<Blah>
\MY_TEXT>

<MY_TEXT="ABC" PATH="EFG"
<location= "QQQ" path="LLL" 
\location>
<R_DATA = MNOP
 <Mylocation ="ghdf" stime=20150301 etime=20150401 >
 <Mylocation ="ghdf" stime=20150401 etime=20150501 >
\R_DATA>
<Blah>
\MY_TEXT>

如果那不是您想要的,并且您无法弄清楚如何调整上述操作,请编辑您的问题以提供与您发布的样本输入相匹配的预期输出。