
我想從文字檔案(“columns.txt”)中提取製表符分隔的列,其中標題(第一行)與另一個文字檔案(“strings.txt”)中列出的某些字串相符。
“columns.txt”看起來像這樣:
rs2438689 rs54666437 rs9877702046 rs025436779...
0 0 0 1
1 1 2 2
0 1 2 0
... ... ... ...
“strings.txt”看起來像這樣:
rs2438689
rs9877702046
...
輸出文字檔案「output.txt」應如下所示(製表符分隔):
rs2438689 rs9877702046...
0 0
1 2
0 2
... ...
關於如何使用 awk 執行此操作有什麼建議嗎?謝謝你!
答案1
取代 Awk,如何從 中建立一個以逗號分隔的列名列表,並將其用作sstrings.txt
的列表:namedcol
csvtool
$ csvtool -t TAB -u TAB namedcol "$(paste -sd, < strings.txt)" columns.txt
rs2438689 rs9877702046
0 0
1 2
0 2
... ...
或與csvcut/csvformat
基於 Python 的類似csvkit
:
$ csvcut -tc "$(paste -sd, < strings.txt)" columns.txt | csvformat -T
rs2438689 rs9877702046
0 0
1 2
0 2
... ...
答案2
和perl
$ perl -F'\t' -lane 'if(!$#ARGV){ $h{$_}=1 }
else{ @i = grep { $h{$F[$_]} == 1 } 0..$#F if !$c++;
print join "\t", @F[@i]}' strings.txt columns.txt
rs2438689 rs9877702046
0 0
1 2
0 2
if(!$#ARGV){ $h{$_}=1 }
對於第一個輸入文件,建立一個以行內容作為鍵的雜湊值@i = grep { $h{$F[$_]} == 1 } 0..$#F if !$c++
對於第二個檔案的第一行,從雜湊中建立所有符合列名稱的索引列表print join "\t", @F[@i]
列印匹配的列
答案3
修改我對你之前問題的解決方案:
awk -F '\t' -f script.awk strings.txt columns.txt
script.awk
哪裡
BEGIN { OFS = FS }
FNR == NR {
columns[$1] = 1
next
}
FNR == 1 {
for (i = 1; i <= NF; ++i)
if ($i in columns)
keep[i] = 1
}
{
nf = split($0, fields, FS)
$0 = ""
j = 0
for (i = 1; i <= nf; ++i)
if (i in keep)
$(++j) = fields[i]
print
}
在這裡,該FNR == NR
區塊只會在讀取命令列 ( strings.txt
) 上列出的第一個檔案時執行。它將使用columns
作為列名稱的鍵填充數組。其餘的代碼是或多或少與舊解決方案相同,除了我們檢查當前列是否是我們想要保留的列(在FNR == 1
區塊中)之外。
解決評論中的問題:
若要始終複製前六列並剪下 處的列標題_
,請變更
FNR == 1 {
for (i = 1; i <= NF; ++i)
if ($i in columns)
keep[i] = 1
}
進入
FNR == 1 {
for (i = 1; i <= NF; ++i) {
sub("_.*", "", $i)
if (i <= 6 || $i in columns)
keep[i] = 1
}
}
答案4
透過使用下面的腳本完成,可能很長時間都可以正常工作
k=wc -l file1| awk '{print $1}'
for ((i=1;i<=$k;i++)); do for j in `cat file2`; do awk -v i="$i" -v j="$j" '$i == j {x=NR+k}(NR<=x){print $i}' file1; done ; done>final.txt
z=`wc -l final.txt| awk '{print $1}'`
for ((i=1;i<=$z;i++)); do j=$(($i+3)); sed -n ''$i','$j'p' final.txt >file_starting_with_$i.txt; i=$j; done
paste file_starting_with*
輸出
rs2438689 rs9877702046
0 0
1 2
0 2