簡體   English   中英

Awk 在 do-while 循環中,讀取多列文件

[英]Awk in do-while loop, read files with multiple columns

我正在編寫一個腳本,它從一個文件的列中讀取變量,與另一個文件的列進行模式匹配,並將整行從另一個文件打印到 output 文件。 我想我已經接近解決方案,但只生成文件輸出中的列名(寫入 NR==1,沒有其他內容)。

while read -r value1 value2
do
        echo "$value2"
        awk -F "\t" 'NR==1; $2 == "$value1" { print $0 }' data.txt > "${value2}".out
done < "var_table.txt" 

這是我的數據的示例頭:

數據.txt

V1  V2  V3  V4
1   dat-131.2   2071.49 3.11E-302
2   dat-219.1   744.48  3.11E-302
3   dat-120.2   13.29   3.11E-302
4   dat-577.1   1.71    3.11E-302
5   dat-535.2   16.07   3.11E-302
6   dat-535.2   12.99   3.11E-302
7   dat-535.2   2147.31 3.11E-302
8   dat-535.2   61.21   3.11E-302
…
    

變量表.txt

dat-501.16  VarA
dat-151.5   VarB
dat-518.9   VarC
dat-535.2   VarD
dat-49.0    VarE

預期的 output 將創建一個名為 VarD.out ("${value2}.out) 的 tsv 文件,其中填充了 header (NR==1),加上 data.txt 中對應於值 "dat-535.2" 的整行" 在第 2 列(如果 $2 == "$value1",則打印 $0)。

VarD.out _|>

V1  V2  V3  V4
5   dat-535.2   16.07   3.11E-302
6   dat-535.2   12.99   3.11E-302
7   dat-535.2   2147.31 3.11E-302
8   dat-535.2   61.21   3.11E-302

我希望這是有道理的,並且可以復制。 我看過其他答案,但無法理解如何合並多列數據。 我的猜測是因為多個文件的變量分配問題,因為$2和$0對應data.txt中的數據,而value1和value2指的是var_table.txt的列? 歡迎任何幫助。

謝謝

修復 OP 的代碼以正確地將bash變量傳遞給awk

while read -r value1 value2
do
        echo "$value2"
        awk -F "\t" -v value="$value1" 'NR==1 || $2==value' data.txt > "${value2}".out
done < "var_table.txt"

在哪里:

  • -v value="$value1" - 將bash變量value1的值分配給awk變量value
  • NR==1 || $2==value NR==1 || $2==value - 如果輸入文件的第一條記錄或第二個字段等於awk變量value (又名bash變量value1 ),則寫入 output 文件

這會產生:

$ head Var*out
==> VarA.out <==
V1      V2      V3      V4

==> VarB.out <==
V1      V2      V3      V4

==> VarC.out <==
V1      V2      V3      V4

==> VarD.out <==
V1      V2      V3      V4
5       dat-535.2       16.07   3.11E-302
6       dat-535.2       12.99   3.11E-302
7       dat-535.2       2147.31 3.11E-302
8       dat-535.2       61.21   3.11E-302

==> VarE.out <==
V1      V2      V3      V4

一種更有效的方法,我們將循環拉入awk

awk '
BEGIN      { FS=OFS="\t" }
FNR==NR    { vars[$1]=$2; next }                 # 1st file: save contents to array vars[] using 1st field as the index
FNR==1     { for (i in vars)                     # 2nd file: write header row to each of our output files (ie, for each index from the vars[] array)
                 print $0 > (vars[i] ".out")
             next
           }
$2 in vars { print $0 > (vars[$2] ".out") }      # 2nd file: if 2nd field is an index in array vars[] then print the current line to the associated output file
' var_table.txt data.txt

筆記:

  • 這種方法將為 var_table.txt 中的每一行打開一個單獨的var_table.txt
  • 對於足夠“大”的行數,這可能會導致awk的某些版本由於文件描述符用完而中止
  • 有幾種方法可以解決這個問題(文件描述符用完),但需要更多編碼和更好地理解輸入數據,例如, data.txt中的所有行(在第二個字段中具有相同的值)總是駐留在data.txt中的連續行上? 或者它們可以分布在整個文件中嗎?

這也會產生:

==> VarA.out <==
V1      V2      V3      V4

==> VarB.out <==
V1      V2      V3      V4

==> VarC.out <==
V1      V2      V3      V4

==> VarD.out <==
V1      V2      V3      V4
5       dat-535.2       16.07   3.11E-302
6       dat-535.2       12.99   3.11E-302
7       dat-535.2       2147.31 3.11E-302
8       dat-535.2       61.21   3.11E-302

==> VarE.out <==
V1      V2      V3      V4

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM