2013-03-05 62 views
0

我想將參數$ 8(文件名)傳遞給函數「testfunc」。該函數應該grep在該文件中的key_word並返回一年。問題在於Linux命令「grep」在fileN中沒有看到任何內容。如果我直接通過$ 8,它仍然沒有看到任何東西。如何將參數傳遞給AWK中的每條處理線

awk ' 
    function testfunc(fileN, my_year) 
    { "grep 'key_word' fileN" | getline my_year 
     return(my_year) 
     close("grep 'key_word' fileN") 
    } 
    BEGIN {OFS="\t"} 
     {printf "%s\t%s\t%s\t", $8, testfunc($8), $9}' 
+1

這絕對是錯誤的做法。您試圖將awk用作shell - 不這樣做,即使您可以強制執行它並生成所需的輸出,awk也不是很好。驚喜,驚喜,外殼非常擅長。如果你告訴我們你真的想要做什麼,我們可以提供幫助。 – 2013-03-05 20:43:43

回答

1

這是你要找的語法:

awk ' 
    function testfunc(fileN,  my_year, cmd) 
    { cmd = "grep \"key_word\" " fileN 
     cmd | getline my_year 
     close(cmd) 
     return(my_year) 
    } 
    BEGIN {OFS="\t"} 
     {printf "%s\t%s\t%s\t", $8, testfunc($8), $9}' 

但正如我在我的評論中提及了 - 不這樣做,它的無論你想要做什麼,都是錯誤的做法。

請注意,您不能在單引號分隔的腳本中使用單引號引號。

編輯:讓我試着澄清我關於使用不同方法的觀點。你似乎有一個文件,我們把它叫做「file1」,它有第8個字段中的另一個文件名,還有其他一些你關心的值在第9個字段中。在第8個字段中命名的所有文件都包含一行,其中包含文本「key_word」,並且要打印的內容是file1中的第8個字段,然後是選項卡,然後是指定文件中的關鍵字行,然後是第9個字段來自file1。

這可以寫成(只有一個可能的解決方案):

gawk -v OFS='\t' ' 
ARGIND < ARGC { if (/key_word/) my_year[FILENAME] = $0; nextfile } 
{ print $8, my_year[$8], $9 } 
' $(awk '{print $8}' file1 | sort -u) file1 

即調用AWK一次在「文件1」中獲得包含要那麼最新信息的文件列表傳遞文件,這些文件列表在「file1」之前再次awk,這樣在最終處理file1時需要的所有信息都會存儲在數組中。

以上使用GNU awk的「下一文件」的效率,但是這不是必需的,GNU awks ARGIND爲清晰起見,但你可以用文件名代替ARGIND < ARGC!= ARGV [ARGC]在非GAWK解決方案。

還有許多其他的解決方案,這一切都取決於你真正想要做....

+0

雖然如果您的腳本位於文件中並且來源(例如源文件),您可以使用單引號。 'awk -f yourscript'。 – 2013-03-06 07:09:06

+0

非常感謝。這有助於我理解在單引號腳本中使用單引號的問題。注意:我知道我可以使用直接shell腳本獲得類似的輸出,但是我需要用'if'或'for'語句編寫大量的代碼行。在這種情況下,我需要的只是改變輸入列的順序並在其間添加一個。 – 2013-03-06 13:43:36

+0

我絕對不是建議在shell中編寫你的整個腳本,我只是建議可能有更好的方法來做任何你想做的事情,因爲shell調用awk來調用shell幾乎總是錯誤的方法,在awk中使用getline充滿了危險。我敢打賭,只要採用正確的方法,無論你在做什麼都是微不足道的。如果您通過一些示例輸入和預期輸出發佈另一個問題,我相信我們可以幫助您。 – 2013-03-06 13:53:32

1

試試這個:

function testfunc(fileN) 
    { 
     cmd="grep 'key_word' " fileN 
     cmd | getline my_year 
     return(sprintf("%s",my_year)) 
    } 
+0

你的消化部分對我有用。它確實執行了grep,但變量my_year(或者系統命令的執行)包含了我不想要的carry-return,因爲它會向文件中添加一個額外的CR。我已經增加了9美元,所以你可以看到,在8美元之後,返回將輸出記錄制動成兩行。 – 2013-03-05 20:27:10

+0

它還會在第一個輸出行中添加** sh:0:command not found **。 – 2013-03-05 20:49:22

+0

實際上,發生的情況是系統命令在「getline」獲取任何內容之前執行,顯示結果。 「my_year」變量沒有得到任何值。換句話說,我看到的輸出是系統命令的輸出,而不是函數返回的內容。 – 2013-03-05 21:02:21

0

感謝埃德和索爾特對你有所幫助。最後,我決定使用shell腳本,因爲除了grep命令之外,我還需要一個sed命令,因爲它需要特殊的字符,所以會出現各種問題。所以我的最終解決方案如下:

fileList=`ls -1 *.xml` 
for f in ${fileList} ; do 
    my_year=`grep -e "key_word" ${f} | sed -n '{s/^.*>\([0-9][0-9]*\)<.*$/\1/p}'` 
    line=`ls -ltr ${f}` 
    line="${line} ${my-year} sthElseHere" 
    echo ${line} 
done | \ 

awk ' BEGIN {print "File Name    \tcol02 \tcol03 " 
      print "=================== \t====== \t============"} 
      {printf "%s\t%s\t%s\n", $8, $4, $9 }' 
相關問題