在文件中搜索一行,然后在linux中用换行符替换下一行模式匹配的行(Shell脚本)



我有一个包含以下数据的文件。让我们称之为myfile.xml:

.........
<header>unique_name</header>
......
somelines
......
<version>I need only this line</version>
......
......
<version>This is second match of version, which I dont want</version>

现在我正在寻找能做以下事情的linux命令:

  1. 可以有许多<header>.*</header>线路。但我需要<header>unique_name</header>。这是一个唯一的标头名称,我会将其作为核心。它在文件中只出现一次,但可以出现在文件中的任何位置。

  2. 在myfile.txt中搜索出现在<header>unique_name</header>之后的<version>.*</version>,应将其替换为<version>new version number</version>

我尝试过使用grepsedawk来实现,但我做不到。请告知。

输入和预期输出:

输入文件"myfile.xml":

  • 字符串查找=<header>unique_name</header>
  • newversionNUMBER=新版本编号

myfile.xml文件内容如下:

<header>Some strings</header>
......Somelines...........
<version>I dont need this line, since header doesnt match stringtoFIND variable</version>
<header>unique_name</header>
.............
<version>I need only this line</version>
...........
..........
<version>I Dont need this line</version>
.........

预期输出

<header>Some strings</header>
......Somelines...........
<version>I dont need this line, since header doesnt match stringtoFIND variable</version>
<header>unique_name</header>
.............
<version>new_version_number</version>
...........
..........
<version>I Dont need this line</version>
.........

使用GNU awk进行第三个参数匹配():

$ cat tst.awk
match($0,/<header>(.*)</header>/,a) {
    inBlock = (a[1] == "unique_name" ? 1 : 0)
}
inBlock && match($0,/(.*<version>).*(</version>.*)/,a) {
    $0 = a[1] "new_version_number" a[2]
    inBlock = 0
}
{ print }
$ awk -f tst.awk file
<header>Some strings</header>
......Somelines...........
<version>I dont need this line, since header doesnt match stringtoFIND variable</version>
<header>unique_name</header>
.............
<version>new_version_number</version>
...........
..........
<version>I Dont need this line</version>
.........

您可以使用这样的awk来完成此操作。

script.awk

/<header>unique_name</header>/ { found=1; done=0 }
/<version>.*</version>/ && found && !done {
      # replace version in $0
      gsub(/<version>.*</version>/,"<version>new_version_number</version>")
      done = 1
    }
# implicitly print current $0:
1

运行脚本:awk -f script.awk yourfile > newfile

打印每一行,并根据founddone中的状态进行版本替换。

类似于Lars Fischer的答案:

#! /usr/bin/awk -f
/<header>.*</header>/ {
    looking = 0
}
 /<header>unique_name</header>/ {
    looking = 1
}
looking && /<version>.*</version>/ {
    n = match($0, /^ *<version>/)
    $0 = substr($0, 1, n) Version "</version>"
    looking = 0    
}
{ print }

我构造了新的版本行,而不是替换它。在规则中,我把布尔值放在正则表达式之前,因为它更高效,你不会注意到。我个人不喜欢用1结尾来表示打印,但这只是一种风格选择。

作为调用

$ awk -v Version="$version" -f script.awk input

相关内容

  • 没有找到相关文章

最新更新