繁体   English   中英

linux|awk|shell 脚本修改多个块中的同名行

[英]linux|awk|shell script modification of line with same name in many blocks

My input file has blocks like below. 

[abc]  
para1=123  
para2=456  
para3=111  

[pqr]  
para1=333    
para2=765    
para3=1345    

[xyz]    
para1=888    
para2=236    
para3=964    

现在我如何在块 pqr 中单独修改 para2 的值而不在其他块或单独的第一个块中更改值。请帮助我使用 awk 或 perl 或 sed 命令实现这一点。提前谢谢

试试这个awk

awk -v RS= -v ORS='\n\n' '/^\[pqr\]/{sub(/para2=[^\n]*/, "para2=foobar")} 1' file
[abc]
para1=123
para2=456
para3=111

[pqr]
para1=333
para2=foobar
para3=1345

[xyz]
para1=888
para2=236
para3=964

我通常使用类似这样的awk命令:

$ awk '/^\[/{b=0} /^\[pqr\]/{b=1} /^para2=/{if(b) {sub(/=.*/, "=newvalue")}} 1' t
[abc]
para1=123
para2=456
para3=111

[pqr]
para1=333
para2=newvalue
para3=1345

[xyz]
para1=888
para2=236
para3=964

这个想法是使用一个布尔变量(这里是b ),当我们进入正确的“块”时它被设置为 1,当你进入另一个块时它被设置回 0。

然后只需通过检查b的值来验证您在后续操作中是否在正确的块中,在这种情况下替换 para2 的值。 我还使用这种技术从配置文件中简单地提取一个特定的“块”。

使用 perl:

#!/usr/bin/env perl
use strict;
use warnings;

#separate records with double line feed. 
local $/ = "\n\n"; 

#iterate stdin or file names specified on command line 
while ( <> ) { 
    #replace if the block starts [pqr]
    s/para2=\d+/para2=9999/m if  m/^\[pqr\]/; 
    print;
}

这个单行代码是;

perl -pe 'BEGIN { $/ = "\n\n" } s/para2=\d+/para2=9999/m if  m/^\[pqr\]/;'

并给出(供您输入):

[abc]  
para1=123  
para2=456  
para3=111  

[pqr]  
para1=333    
para2=9999    
para3=1345    

[xyz]    
para1=888    
para2=236    
para3=964 
awk -v RS=  -v ORS='\n\n' '/pqr/{sub(/para2=765/,"para2=new")}1' file
[abc]  
para1=123  
para2=456  
para3=111  

[pqr]  
para1=333    
para2=new    
para3=1345    

[xyz]    
para1=888    
para2=236    
para3=964    

我只会为此使用 Perl。 用于跟踪当前组的语句。 除了特定组之外,跳过修改的一个语句。 用新值替换 key= 之后的所有内容的语句。

perl -i -ple '$group = $1 if /^\[(.*?)\]/; next unless $group eq "pqr"; s/(?<=^para2=).*/newvalue/' file.conf

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM