在bash中的多行匹配后追加字符串

在bash中的多行匹配后追加字符串,bash,awk,sed,perl,python,c,shell,Bash,Awk,Sed,Perl,Python,C,Shell,我需要一个sed或awk命令在bash中的多行匹配后打印一行。例如,将此文件作为输入: admin: users: - user1 - user2 read_only: users: - user3 write_only: users: - user4 access_only: users: - user5 - user6 …我需要将此作为输出: admin: users: NEW USER - user

我需要一个
sed
awk
命令在bash中的多行匹配后打印一行。例如,将此文件作为输入:

admin:
  users:
    - user1
    - user2

read_only:
  users:
    - user3

write_only:
  users:
    - user4

access_only:
  users:
    - user5
    - user6
…我需要将此作为输出:

admin:
  users:
    NEW USER
    - user1
    - user2

read_only:
  users:
    - user3

write_only:
  users:
    - user4

access_only:
  users:
    - user5
    - user6
正则表达式应该匹配前两行
admin:users:
,然后追加
newuser

如何做到这一点?我应该使用sed还是awk?怎样
也谢谢你。它是YAML,所以将其解析为YAML

#!/usr/bin/env perl

use strict;
use warnings;

use YAML;
use Data::Dumper;

my $stuff = Load ( do { local $/; <DATA> } );

print Dumper $stuff; 

print $stuff->{admin}{users}[0],"\n";

print "List:\n";
print join "\n", @{$stuff->{admin}{users}};

__DATA__
admin:
  users:
    - user1
    - user2
#/usr/bin/env perl
严格使用;
使用警告;
使用YAML;
使用数据::转储程序;
my$stuff=Load(do{local$/;});
打印转储程序$stuff;
打印$stuff->{admin}{users}[0],“\n”;
打印“列表:\n”;
打印join“\n”@{$stuff->{admin}{users};
__资料__
管理员:
用户:
-用户1
-用户2
鉴于您已将问题更新为“向admin users节添加新用户”,我的答案已更改,但仍然是“使用perl”:

#!/usr/bin/env perl

use strict;
use warnings;

use YAML::Syck;
use Data::Dumper;

$YAML::Syck::SortKeys = 1;

my $stuff = Load ( do { local $/; <DATA> } );

print Dumper $stuff; 

push @{$stuff->{admin}{users}}, "new username";

print Dumper $stuff;

print Dump \$stuff;


__DATA__
admin:
  users:
    - user1
    - user2

read_only:
  users:
    - user3

write_only:
  users:
    - user4

access_only:
  users:
    - user5
    - user6
#/usr/bin/env perl
严格使用;
使用警告;
使用YAML::Syck;
使用数据::转储程序;
$YAML::Syck::SortKeys=1;
my$stuff=Load(do{local$/;});
打印转储程序$stuff;
push@{$stuff->{admin}{users}},“新用户名”;
打印转储程序$stuff;
打印转储\$stuff;
__资料__
管理员:
用户:
-用户1
-用户2
只读:
用户:
-用户3
只写以下内容:
用户:
-用户4
仅限访问单元:
用户:
-用户5
-用户6
您可以将此设置为:

perl -0777 -MYAML -e '$s = Load(<>);unshift @{$s->{admin}{users}}, "new username"; print Dump $s;'
perl-0777-MYAML-e'$s=Load();unshift@{$s->{admin}{users}},“新用户名”;打印转储$s;'
这将从标准输入中读取数据,进行转换并输出有效的YAML
unshift
将在数组的开头插入用户名-我通常使用
push
将其插入到数组的末尾


注意-我在上一个示例中使用了
YAML::Syck
,因为它会对输出进行排序

都不是。它是YAML,所以将其解析为YAML

#!/usr/bin/env perl

use strict;
use warnings;

use YAML;
use Data::Dumper;

my $stuff = Load ( do { local $/; <DATA> } );

print Dumper $stuff; 

print $stuff->{admin}{users}[0],"\n";

print "List:\n";
print join "\n", @{$stuff->{admin}{users}};

__DATA__
admin:
  users:
    - user1
    - user2
#/usr/bin/env perl
严格使用;
使用警告;
使用YAML;
使用数据::转储程序;
my$stuff=Load(do{local$/;});
打印转储程序$stuff;
打印$stuff->{admin}{users}[0],“\n”;
打印“列表:\n”;
打印join“\n”@{$stuff->{admin}{users};
__资料__
管理员:
用户:
-用户1
-用户2
鉴于您已将问题更新为“向admin users节添加新用户”,我的答案已更改,但仍然是“使用perl”:

#!/usr/bin/env perl

use strict;
use warnings;

use YAML::Syck;
use Data::Dumper;

$YAML::Syck::SortKeys = 1;

my $stuff = Load ( do { local $/; <DATA> } );

print Dumper $stuff; 

push @{$stuff->{admin}{users}}, "new username";

print Dumper $stuff;

print Dump \$stuff;


__DATA__
admin:
  users:
    - user1
    - user2

read_only:
  users:
    - user3

write_only:
  users:
    - user4

access_only:
  users:
    - user5
    - user6
#/usr/bin/env perl
严格使用;
使用警告;
使用YAML::Syck;
使用数据::转储程序;
$YAML::Syck::SortKeys=1;
my$stuff=Load(do{local$/;});
打印转储程序$stuff;
push@{$stuff->{admin}{users}},“新用户名”;
打印转储程序$stuff;
打印转储\$stuff;
__资料__
管理员:
用户:
-用户1
-用户2
只读:
用户:
-用户3
只写以下内容:
用户:
-用户4
仅限访问单元:
用户:
-用户5
-用户6
您可以将此设置为:

perl -0777 -MYAML -e '$s = Load(<>);unshift @{$s->{admin}{users}}, "new username"; print Dump $s;'
perl-0777-MYAML-e'$s=Load();unshift@{$s->{admin}{users}},“新用户名”;打印转储$s;'
这将从标准输入中读取数据,进行转换并输出有效的YAML
unshift
将在数组的开头插入用户名-我通常使用
push
将其插入到数组的末尾


注意-我在上一个示例中使用了
YAML::Syck
,因为它会对输出进行排序

sed用于单个行上的简单替换,仅此而已。对于其他任何东西,您都应该使用awk,以实现软件的简单性、清晰性、效率、健壮性和其他最理想的属性

对于多字符RS和gensub(),使用GNU awk:


sed用于对单个行进行简单替换,仅此而已。对于其他任何东西,您都应该使用awk,以实现软件的简单性、清晰性、效率、健壮性和其他最理想的属性

对于多字符RS和gensub(),使用GNU awk:

如果您在Unix(或其他不使用回车符的环境)中工作,可以通过临时替换新行来使用sed:

cat file | tr '\n' '\r' | sed "s/admin:\r  users:/admin:\r  users:\r    NEW LINE/g" | tr '\r' '\n'
诚然,它比上面的awk解决方案更具黑客性,但为那些想知道如何轻松使用sed的人添加了这一点。

如果您在Unix(或其他不使用回车符的环境)中工作,您可以通过临时替换新行来使用sed:

cat file | tr '\n' '\r' | sed "s/admin:\r  users:/admin:\r  users:\r    NEW LINE/g" | tr '\r' '\n'
诚然,它比上面的awk解决方案更具黑客性,但为那些想知道如何轻松使用sed的人添加了这一点。

awk解决方案:

awk '/^admin/{ n=NR+2 }NR==n{ sp=substr($0,1,index($0,"-")-1); 
     printf "%s\n%s\n",sp"NEW USER",$0; next  }1' file
输出:

admin:
  users:
    NEW USER
    - user1
    - user2

read_only:
  users:
    - user3

write_only:
  users:
    - user4

access_only:
  users:
    - user5
    - user6
awk解决方案:

awk '/^admin/{ n=NR+2 }NR==n{ sp=substr($0,1,index($0,"-")-1); 
     printf "%s\n%s\n",sp"NEW USER",$0; next  }1' file
输出:

admin:
  users:
    NEW USER
    - user1
    - user2

read_only:
  users:
    - user3

write_only:
  users:
    - user4

access_only:
  users:
    - user5
    - user6
使用
sed
/^[a-z\+://
/^$/
之间划界块,以便可以在一个块中执行somme进程:

sed -e $'/^admin:/,/^$/{/users:/a\    NewUser\n}'
这可以写成:

NEWUSER="user2017"
sed -e "/^admin:/,/^$/{
    /users:/a\    - $NEWUSER
}"
(通过使用双引号,我可以使用命令行或脚本中的变量)

这将导致:

admin:
  users:
    - user2017
    - user1
    - user2

read_only:
  users:
    - user3

...
。。。 可通过以下方式使用:

myadduser NewAdminUser <file.txt
admin:
  users:
    - NewAdminUser
    - user1
    - user2

read_only:
  users:
    - user3

...
但是请, 读

使用原型或类似于使用最终编程的原型,您可能会找到合适的库

也可以在中使用这些库中的任何一个

第一个管理员用户
perl -MYAML -E 'undef$/;$s = Load(<>);say@{$s->{admin}->{users}}[0];'
perl-MYAML-E'unde$/$s=荷载();说@{$s->{admin}->{users}}[0];'
管理员用户数
perl -MYAML -E 'undef$/;$s = Load(<>);say scalar@{$s->{admin}->{users}};' 
perl-MYAML-E'unde$/$s=荷载();说标量@{$s->{admin}->{users}};'
带有
sed
/^[a-z\+://
/^$/
之间划界块,以便可以在一个块中执行somme进程:

sed -e $'/^admin:/,/^$/{/users:/a\    NewUser\n}'
这可以写成:

NEWUSER="user2017"
sed -e "/^admin:/,/^$/{
    /users:/a\    - $NEWUSER
}"
(通过使用双引号,我可以使用命令行或脚本中的变量)

这将导致:

admin:
  users:
    - user2017
    - user1
    - user2

read_only:
  users:
    - user3

...
。。。 可通过以下方式使用:

myadduser NewAdminUser <file.txt
admin:
  users:
    - NewAdminUser
    - user1
    - user2

read_only:
  users:
    - user3

...
但是请, 读

使用原型或类似于使用最终编程的原型,您可能会找到合适的库

也可以在中使用这些库中的任何一个

第一个管理员用户
perl -MYAML -E 'undef$/;$s = Load(<>);say@{$s->{admin}->{users}}[0];'
perl-MYAML-E'unde$/$s=荷载();说@{$s->{admin}->{users}}[0];'
管理员用户数
perl -MYAML -E 'undef$/;$s = Load(<>);say scalar@{$s->{admin}->{users}};' 
perl-MYAML-E'unde$/$s=荷载();说标量@{$s->{admin}->{users}};'
这可能适合您(GNU-sed):

如果该行不包含
admin:
bail out。