
Me gustaría extraer columnas delimitadas por tabulaciones de un archivo de texto ("columns.txt") en el que el encabezado (primera línea) coincide con ciertas cadenas enumeradas en otro archivo de texto ("strings.txt").
"columnas.txt" tiene este aspecto:
rs2438689 rs54666437 rs9877702046 rs025436779...
0 0 0 1
1 1 2 2
0 1 2 0
... ... ... ...
"strings.txt" se ve así:
rs2438689
rs9877702046
...
El archivo de texto de salida "output.txt" debería verse así (delimitado por tabulaciones):
rs2438689 rs9877702046...
0 0
1 2
0 2
... ...
¿Alguna sugerencia sobre cómo hacer esto con awk? ¡Gracias!
Respuesta1
En lugar de Awk, ¿qué tal si hacemos una lista de nombres de columnas separados por comas strings.txt
y la usamos como una lista de namedcol
s para csvtool
:
$ csvtool -t TAB -u TAB namedcol "$(paste -sd, < strings.txt)" columns.txt
rs2438689 rs9877702046
0 0
1 2
0 2
... ...
o de manera similar con csvcut/csvformat
el basado en Python csvkit
:
$ csvcut -tc "$(paste -sd, < strings.txt)" columns.txt | csvformat -T
rs2438689 rs9877702046
0 0
1 2
0 2
... ...
Respuesta2
Conperl
$ 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 }
para el primer archivo de entrada, cree un hash con el contenido de la línea como clave@i = grep { $h{$F[$_]} == 1 } 0..$#F if !$c++
para la primera línea del segundo archivo, cree una lista de índice de todos los nombres de columnas coincidentes del hashprint join "\t", @F[@i]
imprimir las columnas coincidentes
Respuesta3
Modificandomi solución a tu pregunta anterior:
awk -F '\t' -f script.awk strings.txt columns.txt
dónde script.awk
es
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
}
Aquí, el FNR == NR
bloque solo se ejecutaría mientras se lee el primer archivo enumerado en la línea de comando ( strings.txt
). Completaría la columns
matriz con claves que son los nombres de las columnas. El resto del código esmás o menossin cambios con respecto a la solución anterior, aparte de donde verificamos si la columna actual es una que nos gustaría mantener (en el FNR == 1
bloque).
Abordar elpreguntas en comentarios:
Para copiar siempre las primeras seis columnas y cortar los encabezados de las columnas en _
, cambie
FNR == 1 {
for (i = 1; i <= NF; ++i)
if ($i in columns)
keep[i] = 1
}
en
FNR == 1 {
for (i = 1; i <= NF; ++i) {
sub("_.*", "", $i)
if (i <= 6 || $i in columns)
keep[i] = 1
}
}
Respuesta4
Hecho usando el siguiente script, puede que tarde mucho en funcionar bien.
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*
producción
rs2438689 rs9877702046
0 0
1 2
0 2