tengo muchos archivos vcf
HR001.vcf
HR002.vcf
HR003.vcf
HR004.vcf
HR005.vcf
HR006.vcf
HR007.vcf
HR008.vcf
.
.
En eldécima columnade CADA archivo, el encabezado de la columna es $i. En cada archivo, me gustaría reemplazar $i con el nombre base de los archivos. Por ejemplo, para el archivo HR001.vcf, $i=HR001, para HR002.vcf $i=HR002, etc., ¿existe una manera sencilla de hacer esto en Unix? Tengo un macbook pro pero soy nuevo en esto. En realidad, son archivos VCF con campos delimitados por tabulaciones. Sí, cada archivo tiene 236 filas que deben omitirse. Me interesa la fila que empieza con #CHROM, que es la fila #237 y la columna #10 de esa fila 237 contiene $i
Respuesta1
Yo usaría perl
:
perl -F'\t' -i -lape '
if ($F[0] eq "#CHROM" && $F[9] eq q($i)) {
$F[9] = ($ARGV =~ s/\.vcf$//r);
$_ = join "\t", @F
}' -- *.vcf
Respuesta2
Un script como este puede hacer el trabajo:
cd /path/to/direcrtory
for i in *.vcf
do
awk '{if (FNR==1) $10=FILENAME; print}' "$i" >"$i.tmp" && mv -f "$i.tmp" "$i"
done
La "magia" está en la variable FILENAME
que awk
contiene el nombre del archivo de entrada.
Respuesta3
Respuesta4
Suponiendo que sus archivos estén delimitados por espacios, esto debería funcionar:
for f_name in HR[0-9]*.vcf; do
awk -v f="${f_name%.*}" 'NR == 1 {$10 = f}1' "$f_name" > "$f_name.tmp"
mv "$f_name.tmp" "$f_name"
done
Bucle dentro del directorio y tome cada vcf
archivo. Luego elimine la extensión del nombre del archivo ${f_name%.*}
y pásela como parámetro a awk
.
awk
usará esto como nombre de archivo para realizar la sustitución.NOTA: esto debe ejecutarse dentro del mismo directorio del vcf
archivo, si desea ejecutarlo desde otra ruta use lo siguiente:
for f_name in /some/full/path/HR[0-9]*.vcf; do
# remove the path
f="${f_name##*/}"
awk -v f="${f%.*}" 'NR == 1 {$10 = f}1' "$f_name" > "$f_name.tmp"
mv "$f_name.tmp" "$f_name"
done
Si los archivos no están delimitados por espacios, solucione awk FS
.
EDITAR PARA NUEVAS SOLICITUDES Y MEJORAS BASADAS EN @Ed Morton
Me interesa la fila que empieza con #CHROM, que es la fila #237 y la columna #10 de esa fila 237 contiene $i
for f_name in /some/full/path/HR[0-9]*.vcf; do
# remove the path
f="${f_name##*/}"
awk -F'\t' -v f="${f%.*}" 'NR == 237 {$10 = f}1' "$f_name" > "$f_name.tmp" && mv "$f_name.tmp" "$f_name"
done
Esta nueva versión de los scripts reemplaza el nombre del archivo solo en el campo que desee ($10 = f)
y en la línea que desee (NR == 237)
. El awk
parámetro -F\t
establece cómo awk
ver filas y dividirlas en campos.
Nuevamente gracias a @Ed Morton que ha mejorado los scripts originales: Como puede ver, la declaración: mv "$f_name.tmp" "$f_name"
que es el comando para sobrescribir el archivo antiguo con el contenido del nuevo (producido por awk
) se condensa en una línea: awk '' file > tmp && mv tmp file
de esta manera, si el awk
El comando falla, la parte correcta del &&
no se ejecuta y los datos originales se mantendrán seguros.