
Мне бы хотелось извлечь столбцы, разделенные табуляцией, из текстового файла («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, как насчет создания списка имен столбцов, разделенных запятыми strings.txt
, из и использования его в качестве списка namedcol
s для csvtool
:
$ csvtool -t TAB -u TAB namedcol "$(paste -sd, < strings.txt)" columns.txt
rs2438689 rs9877702046
0 0
1 2
0 2
... ...
или аналогично с csvcut/csvformat
Python-based 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
Сделано с помощью скрипта ниже, это может быть долго, но все работало нормально
к=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