[英]Bash: replacing pattern in specific column but only in lines between two patterns
I have files with this kind of structure: 我有这种结构的文件:
abc
def
ghi
...
x x y x x
x x z x x
x x y x x
...
JKL
x x y x x
x x z x x
x x y x x
...
...
*empty line*
mno
pqr
...
...
I would like to copy the whole file to a new file but with some changes. 我想将整个文件复制到一个新文件,但有一些更改。 Fist, I want to affect only the lines between pattern JKL and the next empty line.
拳头,我想只影响模式JKL和下一个空行之间的线。 On top of that, I need to replace every occurrence of the pattern y with a new pattern NEW, but only if it appears in the third column.
最重要的是,我需要用新模式NEW替换模式y的每个匹配项,但前提是它出现在第三列中。
I tried using sed, but I got stuck at how to select columns: 我尝试使用sed,但我不知道如何选择列:
sed -ne '/JKL/,/^$/s/y/NEW/'
this, of course, replaced y with NEW in all columns. 当然,这在所有列中都用NEW替换了y。
I also tried looking up awk, but I could only find examples of the two separate needs I have, and wasn't able to put them together. 我也试过查找awk,但我只能找到我所拥有的两个独立需求的例子,并且无法将它们组合在一起。 How could I do it?
我怎么能这样做?
Third column is something that follows the beginning of a line, a sequence of non-spaces, a spaces, another sequence of non-spaces, and finally a space: 第三列是一行,它跟在行的开头,一系列非空格,一个空格,另一个非空格序列,最后是一个空格:
sed '/^JKL$/,/^$/s/^\([^ ][^ ]* [^ ][^ ]*\) y /\1 NEW /'
or, if your sed supports -r
or -E
: 或者,如果你的sed支持
-r
或-E
:
sed -E '/^JKL$/,/^$/s/^([^ ]+ [^ ]+) y /\1 NEW /'
awk
also allows the range syntax similar to sed
, see How to select lines between two patterns? awk
还允许范围语法类似于sed
,请参阅如何选择两种模式之间的行? for alternate and more flexible ways 用于替代和更灵活的方式
awk '/JKL/,/^$/{if($3=="y") $3="NEW"} 1' ip.txt
/JKL/,/^$/
lines of interest /JKL/,/^$/
感兴趣的行
if($3=="y")
if 3rd field value is exactly the string y
if($3=="y")
如果第3个字段值恰好是字符串y
$3="NEW"
change the 3rd field value to desired text $3="NEW"
将第3个字段值更改为所需文本 sub(/y/, "NEW", $3)
or gsub(/y/, "NEW", $3)
sub(/y/, "NEW", $3)
或gsub(/y/, "NEW", $3)
1
idiomatic way to print contents of $0
1
打印$0
内容的惯用方法 Using GNU awk and split()
. 使用GNU awk和
split()
。 First some more descriptive test data: 首先是一些更具描述性的测试数据:
...
JKL
x x y x x
x y z x x
...
Then the script: 然后脚本:
$ awk '
/JKL/,/^ *$/ { # the desired block
n=split($0,a,FS,seps) # split and store the separators
b=seps[0] # seps[0] has the leading space, init buffer with it
for(i=1;i<=n;i++) { # iterate all fields
if(i==3 && a[i]=="y") # if 3rd field is y
a[i]="NEW" # replace it with with NEW
b=b a[i] seps[i] # build the buffer for output
}
print b
}' file
and the output: 和输出:
JKL
x x NEW x x
x y z x x
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.