2016-01-09 153 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}' 

上面的代碼可被使用。 此外,我想從其他人那裏獲得有關上述版本優化代碼片段的輸入。