我有一个包含以下数据的文件。请将其称为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命令:
可以有许多<header>.*</header>
行。但是我需要<header>unique_name</header>
。这是一个唯一的标题名称,我会用它来核心。它只出现在文件中一次,但可以出现在文件的任何位置。
搜索myfile.txt中<version>.*</version>
之后显示的<header>unique_name</header>
,并将其替换为<version>new version number</version>
。
我尝试使用grep
,sed
,awk
进行实施,但我做不到。请指教。
输入和预期输出:
输入文件&#34; myfile.xml&#34;:
<header>unique_name</header>
以下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>
.........
答案 0 :(得分:1)
使用GNU awk为第3个arg匹配():
$ 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>
.........
答案 1 :(得分:0)
你可以用这样的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
打印每一行,并根据found
和done
中的状态更换版本。
答案 2 :(得分:0)
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