2016-01-09 98 views
1

如何使用awk创建下面的输出?我无法为逗号分隔的数据创建循环。awk脚本来读取txt文件

awk '{print "echo "$1"\nadd "$2"\nremove "$3"\nlist "$4}' test.txt

的test.txt

1 abc,bcd xyz,yza qwe,wer 
2 abc xyz qwe 
3 abc xyz,yza qwe,wer 
4 abc,bcd xyz wer 

输出:

echo 1 
add abc 
add bcd 
remove xyz 
remove yza 
list qwe 
list wer 
echo 2 
add abc 
remove xyz 
list qwe 
echo 3 
add abc 
remove xyz 
remove yza 
list qwe 
list wer 
echo 4 
add abc 
add bcd 
remove xyz 
list wer 

回答

0

另一种可供选择的方法是两级awk

$ awk '{ print "echo " $1; print "add " $2; print "remove " $3}' file 
    | awk -F'[ ,]' 'NF==3{print $1,$2; print $1,$3;next}1' 
+0

谢谢karakfa。你能解释第二个awk语句吗?它适用于示例输入,但我试图修改此为我的原始输入。 – user5420138

+0

那么,它假定你将有1或2个子字段。第二awk通过空格和逗号分割字段。对于2个子场,NF将是3,将其余分成两行。这将适用于样本集,但更多子字段可能难以扩展。如果这是您的输入,循环解决方案可能会更好。 – karakfa

+0

这里是我的输入文件中的一行:“abc bcd cde def:fed fed:abc,bcd”我需要将fed:abc,bcd分割为两行:“abc bcd cde def:fed fed:abc”“ abc bcd cde def:fed fed:bcd“ – user5420138

0

你有两个环路,这就是为什么你有一个问题 - 你需要的分裂在空白行上,然后用逗号分割子元素。

我会建议使用perl

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

my @actions = qw (echo add remove list); 

#iterate the lines  
while (<DATA>) { 
    #split on whitespace 
    my @fields = split; 
    #iterate actions and fields 
    foreach my $action (@actions) { 
     #split each field on , 
     #print action and field for each. 
     print "$action $_\n" for split (",", shift @fields); 
    } 
} 

__DATA__ 
1 abc,bcd xyz,yza qwe,wer 
2 abc xyz qwe 
3 abc xyz,yza qwe,wer 
4 abc,bcd xyz wer 

这给我们:

echo 1 
add abc 
add bcd 
remove xyz 
remove yza 
list qwe 
list wer 
echo 2 
add abc 
remove xyz 
list qwe 
echo 3 
add abc 
remove xyz 
remove yza 
list qwe 
list wer 
echo 4 
add abc 
add bcd 
remove xyz 
list wer 

我认为这是你想要的吗?

这可以减少到一个班轮:

perl -ane 'for my $act (qw (echo add remove list)) { print "$act $_\n" for split ",", shift @F }' test.txt 
2

我总觉得AWK失去了一下它的潇洒,当我不得不通过所产生的阵列做我自己的分裂和循环,但这里是一个使用功能简单的方法来添加第二个循环,以处理您的空间分隔的字段(本身是逗号分隔值):

$ cat test.awk 
function print_all(label, values) { 
    split(values, v, ",") 
    for (i=1; i<=length(v); ++i) { 
     print label " " v[i] 
    } 
} 

{ 
    print "echo " $1 
    print_all("add", $2) 
    print_all("remove", $3) 
    print_all("list", $4) 
} 

$ cat test.txt 
1 abc,bcd xyz,yza qwe,wer 
2 abc xyz qwe 
3 abc xyz,yza qwe,wer 
4 abc,bcd xyz wer 

$ awk -f test.awk test.txt 
echo 1 
add abc 
add bcd 
remove xyz 
remove yza 
list qwe 
list wer 
echo 2 
add abc 
remove xyz 
list qwe 
echo 3 
add abc 
remove xyz 
remove yza 
list qwe 
list wer 
echo 4 
add abc 
add bcd 
remove xyz 
list wer 
+1

谢谢雅,这个解决方案也工作。 – user5420138

0

不一定建议,但如果你正在寻找紧凑,你可以更换包含换行符的额外文本的逗号。

a = "," $2; b = "," $3; c = "," $4; 
gsub(/,/, "\nadd ", a); 
gsub(/,/, "\nremove ", b); 
gsub(/,/, "\nlist ", c); 
print "echo " $1 a b c "\n" 
0
$ cat tst.awk 
BEGIN { split("echo add remove list",names) } 
{ 
    for (fldNr=1;fldNr<=NF;fldNr++) { 
     split($fldNr,subFlds,/,/) 
     for (subFldNr=1;subFldNr in subFlds; subFldNr++) { 
      print names[fldNr], subFlds[subFldNr] 
     } 
    } 
} 

$ awk -f tst.awk file 
echo 1 
add abc 
add bcd 
remove xyz 
remove yza 
list qwe 
list wer 
echo 2 
add abc 
remove xyz 
list qwe 
echo 3 
add abc 
remove xyz 
remove yza 
list qwe 
list wer 
echo 4 
add abc 
add bcd 
remove xyz 
list wer 
0
awk -F" " '{for(i=1;i<=NF;i++){a[i]=$i;} {print "echo "a[1]"\n""add "a[2]"\nremove "a[3]"\nlist "a[4];}}' filename | awk -F" " '{sub(/,/,"\n"$1" ",$0);print}' 

上面的代码可被使用。 此外,我想从其他人那里获得有关上述版本优化代码片段的输入。