Tengo más de 1000 líneas en un archivo. El archivo comienza de la siguiente manera (se agregaron números de línea):
Station Name
Station Code
A N DEV NAGAR
ACND
ABHAIPUR
AHA
ABOHAR
ABS
ABU ROAD
ABR
Necesito convertir esto en un archivo, con entradas separadas por comas uniendo cada dos líneas. Los datos finales deberían verse como
Station Name,Station Code
A N DEV NAGAR,ACND
ABHAIPUR,AHA
ABOHAR,ABS
ABU ROAD,ABR
...
Lo que estaba intentando era: tratar de escribir un script de shell y luego echo
con una coma en el medio. Pero supongo que una línea más simple y efectiva haría el trabajo aquí puede estar en sed
/ awk
.
¿Algunas ideas?
Respuestas:
Simplemente use
cat
(si le gustan los gatos ;-)) ypaste
:Explicación:
paste
lee de varios archivos y pega las líneas correspondientes (línea 1 del primer archivo con la línea 1 del segundo archivo, etc.):En lugar de un nombre de archivo, podemos usar
-
(guión).paste
toma la primera línea del archivo1 (que es stdin). Luego, quiere leer la primera línea del archivo2 (que también es estándar). Sin embargo, dado que la primera línea de stdin ya se leyó y procesó, lo que ahora espera en la secuencia de entrada es la segunda línea de stdin, quepaste
felizmente se pega a la primera. La-d
opción establece que el delimitador sea una coma en lugar de una pestaña.Alternativamente, hacer
PD Sí, uno puede simplificar lo anterior a
o
que tiene la ventaja de no usar
cat
.Sin embargo, no utilicé este idioma a propósito , por razones de claridad, es menos detallado y me gusta
cat
(LOS GATOS SON AGRADABLES). Así que por favor no edites.Alternativamente, si prefiere pegar a gatos (pegar es el comando para concatenar archivos horizontalmente, mientras que gato los concatena verticalmente), puede usar:
fuente
paste
comando funciona perfectamente, ¿puede darnos un poco más de explicación? Los guiones ???cat
argumento. Nosed "N;s/\n/,/" file.in > file.out
funcionaEn caso de que alguien que aterriza aquí esté buscando combinar todas las líneas en un revestimiento CSV, intente
fuente
Usando sed, une (N) cada 2 líneas y reemplaza la nueva línea (\ n) con ",".
fuente
También tenga en cuenta que debido a que simplemente estamos reemplazando un carácter con otro (cada línea nueva con una coma), podemos trabajar en el archivo de entrada en su lugar:
(pero tenga en cuenta que podría no funcionar en sistemas que no sean Unix que tengan terminadores CRLF (como los de Microsoft) que algunos POSIX emulados
paste
podrían tratar de una manera que no sea Unix)fuente
1
aquí1<>
? ¿Es eso un error tipográfico?Aquí hay una línea (aunque potencialmente millones de comandos-run-er) usando Bash puro:
Utilizo una subshell (la parántesis) para no tener que almacenar y restaurar
IFS
. De lo contrario, qué debería hacer para no estropear el entorno de los usuarios en caso de que se obtenga la fuente. La alternativa sería pasar que los nuevos IFS sólo pararead
que enIFS= read -r name
,IFS= read -r code
.El hecho de que todos los comandos del bucle estén integrados en el shell hace que su rendimiento sea aceptable y es incluso más rápido que las otras soluciones para archivos pequeños. Pero muchas personas lo considerarían una mala práctica y uno debe tener cuidado al generalizarlo a cualquier otra cosa.
fuente
while IFS='\n' read -r name; do IFS='\n' read -r code ... done < file.in
, lo cual es un idioma que a menudo veo en los scripts de shell. El-r
indicador aread
significa "interpretar el carácter '\' seguido del carácter 'n' en la secuencia estándar como dos caracteres, en lugar de como una nueva línea". Podría decirse que puede ser más estético crear la subshell como lo hace que repetirlaIFS='\n'
.-r
Mejoraron técnicamente la solución. ¡Excelente! No soy fanático de la idea de pasar un cambioIFS
dos veces. Si hubiera usado una lectura, super agradable, pero no dos veces. Por supuesto que es una cuestión de opinión . El uso de una subshell es un poco mayor que el conocimiento general de Bash, diría, por lo que mucha gente tendrá problemas para comprender su propósito. Eso es algo maloPara el conjunto completo de respuestas, una posible
awk
solución puede ser:fuente
printf
? Fallará en el raro caso cuando el nombre de una estación contiene un especificador de formato. (Consulte pastebin.com/wgxFttrJ para ver un ejemplo). Pero esto es solo una suposición, el voto negativo no es mío.Canoso viejo castaño de un
awk
idiomafuente
awk '{ORS=NR%2?",":"\n"};1'
es más corto y más idiomáticoprint
la intención y es clara.1
es tan claro para las personas mayoresawk
como yo, pero prefieroprint
sed
por un tiempo antes de buscar, peroawk
hice que combinar cada 4 líneas sea más fácil. Me salvó un viaje a la$EDITOR
!Posible con perl también,
perl -pe 's/^\d+\.\s+//;$.&1?chomp:print","' file
fuente
Por ejemplo:
Salida: (nota:
xargs -L number_of_columns
funciona bien con la mayoría de las columnas, no solo cada dos líneas)fuente
Solución POSIX con
pr
:http://pubs.opengroup.org/onlinepubs/9699919799/utilities/pr.html
fuente