Tengo un archivo de control: cntl.txt
2
3
5
Archivo de datos: datos.txt
red
blue
yellow
green
violet
orange
Necesito leer las líneas que coinciden desde el archivo de control, aquí el resultado esperado es:
blue
yellow
violet
Respuesta1
Ejemplo de una solución muy ineficiente:
for i in $(<control.txt); do awk -v c=$i 'NR~c{ print $0 }' data.txt; done;
También informo una buena solución que aprendí esta noche:
awk 'FNR==NR{ z[$0]++;next }; FNR in z' control.txt data.txt
Respuesta2
Usando soloPOSIX especificadocaracterísticas de Sed:
sed -n -e "$(sed '/./s/$/p/' cntl.txt)" data.txt
Por supuesto, si su cntl.txt
archivo tiene líneas además de números, es posible que obtenga un error. Pero si tiene líneas vacías, estas se manejarán correctamente (es decir, no afectarán la salida).
Respuesta3
Prueba esto:
join <(nl data.txt|sort -k1b,1) <(cat cntl.txt|sort -k1b,1) | sort -nk1,1 | cut -d' ' -f2-
nl - enumerará líneas para usted
1 red
2 blue
3 yellow
4 green
5 violet
6 orange
| sort -k1b,1 - los ordenará por el número de línea (primer campo), lexicográficamente
gato cntl.txt| sort -k1b,1 - ordenará el archivo de control en el mismo orden
2
3
5
join <() <() - unirá los "datos" ordenados (y numerados) con el "control" ordenado, en el primer campo (es decir, número de línea)
2 blue
3 yellow
5 violet
|sort -nk1,1 - reordenará los resultados numéricamente (para volver a ordenar las líneas)
| cut -d'' -f2- - eliminará el campo de número de línea
blue
yellow
violet
Respuesta4
Otra posible solución:
IFS=$'\n' read -d '' -r -a colors < 'data.txt'; unset IFS;
for i in $(<cntl.txt); do
echo ${colors[i-1]}
done
La línea IFS configura el separador de archivos interno como nueva línea e inserta cada línea de data.txt en la matriz. Después de eso, recorre las líneas en cntl.txt e imprime los elementos de la matriz con el índice dado (menos 1 porque comienza su data.txt desde 1, no desde 0, de lo contrario sería innecesario).