python - script - Recoger líneas de un archivo basado en números de línea en otro archivo
awk unix (3)
Tengo dos archivos: uno contiene las direcciones (números de línea) y el otro, como este:
archivo de dirección:
2
4
6
7
1
3
5
archivo de datos
1.000451451
2.000589214
3.117892278
4.479511994
5.484514874
6.784499874
7.021239396
Quiero aleatorizar el archivo de datos basado en el número de archivos de direcciones, así que obtengo:
2.000589214
4.479511994
6.784499874
7.021239396
1.000451451
3.117892278
5.484514874
Quiero hacerlo en python o en bash, pero aún no encontré ninguna solución.
Con awk
:
awk ''NR==FNR {a[NR]=$0; next} {print a[$0]}'' data.txt addr.txt
NR==FNR {a[NR]=$0; next}
NR==FNR {a[NR]=$0; next}
crea una matriz asociativaa
con las claves siendo el número de registro (línea) y los valores siendo el registro completo, esto sería aplicable solo para el primer archivo (NR==FNR
), que esdata.txt
.next
haceawk
para ir a la siguiente línea sin procesar el registro más{print a[$0]}
imprime el valor de la matriz con las claves como el número de línea (registro) del archivoaddr.txt
(addr.txt
)
Ejemplo:
% cat addr.txt
2
4
6
7
1
3
5
% cat data.txt
1.000451451
2.000589214
3.117892278
4.479511994
5.484514874
6.784499874
7.021239396
% awk ''NR==FNR {a[NR]=$0; next} {print a[$0]}'' data.txt addr.txt
2.000589214
4.479511994
6.784499874
7.021239396
1.000451451
3.117892278
5.484514874
Puedes hacerlo, también, dentro de Python
, como en este ejemplo:
with open("address_file", ''r'') as f1, open("data_file", "r") as f2:
data1 = f1.read().splitlines()
data2 = f2.read().splitlines()
for k in data1:
# Handle exceptions if there is any
try:
print(data2[int(k)-1])
except Exception:
pass
Editar: Como se sugirió @heemayl, aquí hay otra solución que usa solo una list
:
with open("file1", ''r'') as f1, open("file2", ''r'') as f2:
data = f2.read().splitlines()
for k in f1.read().splitlines():
print(data[int(k)-1])
Ambos producirán:
2.000589214
4.479511994
6.784499874
7.021239396
1.000451451
3.117892278
5.484514874
Si no te importa sed
, podemos usar la sustitución de procesos para lograr esto fácilmente:
sed -nf <(sed ''s/$/p/'' addr.txt) data.txt
-
-n
suprime la impresión predeterminada -
-f
hace que los comandos de lecturased
de la sustitución de proceso<(...)
-
<(sed ''s/$/p/'' addr.txt)
crea comandos de impresiónsed
basados en números de línea enaddr.txt
Da la salida:
2.000589214
4.479511994
6.784499874
7.021239396
1.000451451
3.117892278
5.484514874