Text-Processing
使用 awk 檢查一個變數中一組特定列的每一行中的資訊與另一個變數中三個特定列中的所有行
我今天之前問過一個非常相似的問題,但是我意識到我需要增加命令的參數。我為另一個參數編輯了命令,但是下一個參數我沒有成功,我不知道為什麼。這是我正在嘗試(並且失敗)解決的問題。
我需要檢查一個變數中的一組特定列上的每一行中的資訊與另一個變數中兩個特定列中的所有行,使用
awk
,保持第一個變數中滿足參數的行。到目前為止,我嘗試通過一個強大的
awk
命令來執行此操作都失敗了。我顯然可以在外部循環中執行此操作,但它會非常慢,因為我有 100 條數千行要檢查。我感謝解決這個問題的任何和所有幫助,我一直在尋求改進我對 awk 的使用,所以如果你有一個解決方案,最好有一個解釋,這樣我就可以學習和提高自己。這是一個例子:
- 假設我只想列印來自 的行
${ListToCheckFrom}
,如果第 2 列 >= 並且第 3 列 <= 到來自${ListToCheckAgainst}
. 此外,第 1 列${ListToCheckFrom}
必須與第 1 列相同${ListToCheckAgainst}
- 輸入範例:
ListToCheckFrom="r,2,3 C,22,24 C,12,13 C,51,59 C,15,20 C,13,18" ListToCheckAgainst="C,25,50 C,22,30 C,12,18 C,15,17 C,1,12 C,60,200"
- 預期輸出:
C,22,24 C,12,13 C,15,20 C,13,18
- 我從一個答案(感謝@AdminBee)到我今天問的一個更簡單的問題:
awk -F',' 'list=="constraints"{n++; low[n]=$2;high[n]=$3;c[n]=$1;next} {for (i=1;i<=n;i++) {if (($1==c[i])&&($2>=low[i]&&$2<=high[i])||($3>=low[i]&&$3<=high[i])) {print;next};}}' list=constraints <(echo "$ListToCheckAgainst") list=check <(echo "$ListToCheckFrom")
我正在使用 Ubuntu。
基於您對上一個問題的另一個答案:
$ cat tst.sh #!/usr/bin/env bash ListToCheckFrom="r,2,3 C,22,24 C,12,13 C,51,59 C,15,20 C,13,18" ListToCheckAgainst="C,25,50 C,22,30 C,12,18 C,15,17 C,1,12 C,60,200" awk ' BEGIN { FS="," } NR==FNR { vals[NR] = $0 next } { for ( nr in vals ) { split(vals[nr],v) if ( (v[1] == $1) && ( (v[2] <= $2) && ($2 <= v[3]) ) ) { print next } } } ' <(printf '%s\n' "$ListToCheckAgainst") <(printf '%s\n' "$ListToCheckFrom")
$ ./tst.sh C,22,24 C,12,13 C,15,20 C,13,18
關於您詢問修改的腳本,這是您上一個問題的答案:
awk -F',' 'list=="constr"{n++; low[n]=$2;high[n]=$3;next} {for (i=1;i<=n;i++) {if ($2>low[i]&&$2<high[i]) {print;next};}}' \ list=constr <(echo "$ListToCheckAgainst") \ list=chk <(echo "$ListToCheckFrom")
您嘗試增強它的第一步應該是使它更易於閱讀,例如,如果您執行 awk 部分
gawk -o-
並在其周圍添加 shell 部分,您會得到以下資訊:awk -F',' ' list == "constr" { n++ low[n] = $2 high[n] = $3 next } { for (i = 1; i <= n; i++) { if ($2 > low[i] && $2 < high[i]) { print next } } } ' \ list=constr <(echo "$ListToCheckAgainst") \ list=chk <(echo "$ListToCheckFrom")
希望從那裡可以很容易地看到要使其滿足您的新要求所需要做的一切就是將其更改為:
awk -F',' ' list == "constr" { n++ key[n] = $1 low[n] = $2 high[n] = $3 next } { for (i = 1; i <= n; i++) { if ( (key[i] == $1) && ($2 > low[i] && $2 < high[i]) ) { print next } } } ' \ list=constr <(echo "$ListToCheckAgainst") \ list=chk <(echo "$ListToCheckFrom")