AWK:將 shell 變數傳遞給 awk

AWK:將 shell 變數傳遞給 awk

我正在嘗試透過多變的從 shell 腳本到表格的模式識別子集的參數數量。到目前為止,這是我的嘗試:

文件“infile”:

    ID,GROUP
    1,GROUP2    
    2,GROUP2    
    3,GROUP4    
    4,GROUP4    
    5,GROUP5    
    6,GROUP5    
    7,GROUP23   
    8,GROUP23   
    9,GROUP23   

檔案subset.sh:

    #!/bin/sh
    rm -f outfile_$week

    week = $1
    shift

    for TOKEN in "$@"
    do

    echo "adding records for" $TOKEN

    awk -F "," -v group = $TOKEN '{ if(FNR > 2 && $2 ~/group/){print $0} }' infile >> outfile_$week
    done

我還嘗試過 group = "$TOKEN", "group = $TOKEN" ,然後都用單引號。我這樣提交:

    sh subset.sh 061314 GROUP2 GROUP23

我得到的錯誤訊息非常少

    Usage: awk [-F fs][-v Assignment][-f Progfile|Program][Assignment|File] ...

非常感謝任何幫助,謝謝!

編輯:我嘗試跑步

    awk -F "," -v group ="GROUP1" '{ if(FNR > 2 && $2 ~/group/){print $0} }' infile

無濟於事...(與上面相同的錯誤)有人知道這可能發生的任何原因嗎?

答案1

你應該寫:

-v group="$TOKEN"

而不是-v group = $TOKEN,這會導致 中的語法錯誤awk

答案2

聽起來像你想要的:

awk -F, '
  BEGIN {
    for (i = 1; i < ARGC; i++) group[ARGV[i]]
    ARGC=0
  }
  NR >= 2 && $2 in group' "$@" < infile

或者,如果您確實想將參數視為正規表示式來匹配第二列:

awk -F, '
  BEGIN {
    for (i = 1; i < ARGC; i++) group[ARGV[i]]
    ARGC=0
  }
  NR >= 2 {
    for (i in group) if ($2 ~ i) {print; next}
  }' "$@" < infile

答案3

您面臨的直接問題是等號周圍的空格。這個選項的參數-v應該是一個賦值。 awk 看到 的參數-v,後面跟著腳本 ( =),然後是檔案名稱( 的值TOKEN、您的腳本和您的檔案名稱)。

您在 shell 腳本中犯了類似的錯誤:week = $1應該是week="$1"

順便一提,總是在指令替換兩邊加上雙引號。例如,如果TOKENis *,它將被目前目錄中的檔案清單取代。

awk -v "group=$TOKEN"

不過,這不會設定group為 的值TOKEN,因為 awk 將賦值的右側視為 awk 語法中的文字。例如,如果 的值為TOKEN7 個字元的字串foo\bar,則 awk 變數group將設定為 6 個字元的字串foo␈ar,其中是退格字元(位元組值 8)。

將變數傳遞給 awk 腳本的直接方法是將其匯出到環境中,並透過陣列使用它ENVIRON

此外,您沒有group在 awk 腳本中的任何地方使用該變數。正規/group/表示式符合包含 5 個字元的 string 的任何字串group。如果您想檢查該欄位是否恰好等於 的值group(例如,如果 的值TOKENGROUP2則包含的欄位GROUP24將不會相符),請使用相等運算符==

  export TOKEN
  awk -F "," '{ if (FNR > 2 && $2 == ENVIRON["TOKEN"]){print $0} }' infile >> outfile_$week

這是整個腳本,進一步簡化為使用 awk 的條件動作語法(這裡省略了動作,因為這print $0是預設的)並避免每次都打開輸出檔:

#!/bin/sh
week="$1"
shift
for TOKEN in "$@"
do
  echo "adding records for" $TOKEN
  awk -F "," 'FNR > 2 && $2 == ENVIRON["TOKEN"]' infile 
done >"outfile_$week"

斯特凡·查澤拉斯的回答使用 awk 的更高級方法不需要多次處理輸入檔。

相關內容