2013-05-03 68 views
0

我有一个stanza格式的文件。该文件的示例如下。使用sed/awk处理stanza格式的文件

id_1: 
     id=241 
     pgrp=staff 
     groups=staff 
     home=/home/id_1 
     shell=/usr/bin/ks 
id_2: 
     id=242 
     pgrp=staff 
     groups=staff 
     home=/home/id_2 
     shell=/usr/bin/ks 

如何使用awk或者sed来处理它,在一个单一的线和制表符分隔格式仅返回ID名称,ID和组?例如为:

id_1  241  staff 
id_2  242  staff 
+0

除id名外还可以包含':'? – abasu 2013-05-03 08:20:56

回答

0

下面是一个AWK溶液:

0123:

translate.awk

#!/usr/bin/awk -f 
{ 
    if(match($1, /[^=]:[ ]*$/)){ 
    id_=$1 
    sub(/:/,"",id_) 
    } 
    if(match($1,/id=/)){ 
    split($1,p,"=") 
    id=p[2] 
    } 
    if(match($1,/groups=/)){ 
    split($1,p,"=") 
    print id_," ",id," ",p[2] 
    } 
} 

或者通过执行它

awk -f translated.awk data.txt 

为了完整起见,这里来缩短版本:

#!/usr/bin/awk -f 
$1 ~ /[^=]:[ ]*$/ {sub(/:/,"",$1);printf $1" ";FS="="} 
$1 ~ /id/   {printf $2" "} 
$1 ~ /groups/  {print $2} 
+0

对于一个相当简单的工作来说不是太复杂吗? – abasu 2013-05-03 07:07:32

+0

你有更简单的* working *解决方案吗?你是什​​么意思的复杂? – hek2mgl 2013-05-03 07:09:49

+0

嗨,如果某些id没有'id_'格式呢?我已经尝试过,如果(匹配($ 1,/^[A-Za-z0-9 _。/))){'在第3行,但它似乎不起作用。 – Schmidtty 2013-05-03 07:11:29

2

与AWK:

BEGIN { FS="="} 

$1 ~ /id_/ { printf("%s", $1) } 

$1 ~ /id/ && $1 !~ /_/ { printf("\t%s", $2) } 

$1 ~ /groups/ { printf("\t%s\n", $2) } 
+0

这会在ID后留下':'。 – 2013-05-03 09:34:40

0
sed 'N;N;N;N;N;y/=\n/ /' data.txt | awk '{print $1,$3,$7}' 
+0

这会在ID后留下':'。 – 2013-05-03 09:35:03

0

这是通过设置RS一衬垫的方法:

awk 'NR>1{print "id_"++i,$3,$7}' RS='id_[0-9]+:' FS='[=\n]' OFS='\t' file 
id_1 241  staff 
id_2 242  staff 

要求GNU awk,假设ID是递增的顺序从1开始的

如果该ID的顺序是任意的:

awk '!/shell/&&NR>1{gsub(/:/,"",$1);print "id_"$1,$3,$5}' RS='id_' FS='[=\n]' OFS='\t' file 
id_1 241  staff 
id_2 242  staff 
0
awk -F"=" '/id_/{split($0,a,":");}/id=/{i=$2}/groups/{printf a[1]"\t"i"\t"$2"\n"}' your_file 

如下测试:

> cat temp 
id_1: 
     id=241 
     pgrp=staff 
     groups=staff 
     home=/home/id_1 
     shell=/usr/bin/ks 
id_2: 
     id=242 
     pgrp=staff 
     groups=staff 
     home=/home/id_2 
     shell=/usr/bin/ks 
> awk -F"=" '/id_/{split($0,a,":");}/id=/{i=$2}/groups/{printf a[1]"\t"i"\t"$2"\n"}' temp 
id_1 241  staff 
id_2 242  staff 
+0

什么!?你甚至读过这个问题吗? – 2013-05-03 10:10:15

+0

对不起更新了我的回答 – Vijay 2013-05-03 10:11:44

0

这可能会为工作你(GNU sed):

sed -rn '/^[^ :]+:/{N;N;N;s/:.*id=(\S+).*groups=(\S+).*/\t\1\t\2/p}' file 

寻找一条持有id的线,然后获得接下来的3条线并重新排列输出。