script reemplazar manejo lineas linea leer fichero extraer eliminar ejemplos comando cadenas cadena buscar bash awk sed grep

bash - manejo - sed reemplazar/



¿Cómo fusionar cada dos líneas en una desde la línea de comando? (20)

"ex" es un editor de líneas programable que pertenece a la misma familia que sed, awk, grep, etc. Creo que podría ser lo que estás buscando. Muchos vi-clones / sucesores modernos también tienen un modo vi.

ex -c "%g/KEY/j" -c "wq" data.txt

Esto dice que para cada línea, si coincide con "KEY", realice un j oin de la siguiente línea. Después de que el comando se complete (contra todas las líneas), emita un mensaje y una orden.

Tengo un archivo de texto con el siguiente formato. La primera línea es la "CLAVE" y la segunda línea es el "VALOR".

KEY 4048:1736 string 3 KEY 0:1772 string 1 KEY 4192:1349 string 1 KEY 7329:2407 string 2 KEY 0:1774 string 1

Necesito el valor en la misma línea que la clave. Entonces la salida debería verse así ...

KEY 4048:1736 string 3 KEY 0:1772 string 1 KEY 4192:1349 string 1 KEY 7329:2407 string 2 KEY 0:1774 string 1

Sería mejor si pudiera usar algún delimitador como $ o,:

KEY 4048:1736 string , 3

¿Cómo combino dos líneas en una?


Alternativa a sed, awk, grep:

xargs -n2 -d''/n''

Esto es mejor cuando desea unir N líneas y solo necesita una salida delimitada por espacios.

Mi respuesta original fue xargs -n2 que se separa en palabras en lugar de líneas. -d se puede usar para dividir la entrada por cualquier carácter individual.


Aquí está mi solución en bash:

while read line1; do read line2; echo "$line1, $line2"; done < data.txt


Aquí hay otra manera con awk :

awk ''ORS=NR%2?FS:RS'' file

$ cat file KEY 4048:1736 string 3 KEY 0:1772 string 1 KEY 4192:1349 string 1 KEY 7329:2407 string 2 KEY 0:1774 string 1

$ awk ''ORS=NR%2?FS:RS'' file KEY 4048:1736 string 3 KEY 0:1772 string 1 KEY 4192:1349 string 1 KEY 7329:2407 string 2 KEY 0:1774 string 1

Según lo indicado por Ed Morton en los comentarios, es mejor agregar llaves para seguridad y parens para portabilidad.

awk ''{ ORS = (NR%2 ? FS : RS) } 1'' file

ORS significa Output Record Separator. Lo que estamos haciendo aquí es probar una condición usando el NR que almacena el número de línea. Si el módulo de NR es un valor verdadero (> 0) entonces establecemos el Separador de Campo de Salida al valor de FS (Separador de Campo) que por defecto es espacio, de lo contrario asignamos el valor de RS (Separador de Registro) que es nueva línea.

Si desea agregar , como separador, use lo siguiente:

awk ''{ ORS = (NR%2 ? "," : RS) } 1'' file


Aunque parece que las soluciones anteriores funcionarían, si se produce una sola anomalía en el documento, la salida se haría pedazos. Debajo está un poco más seguro.

sed -n ''/KEY/{ N s//n/ /p }'' somefile.txt


En el caso en que necesitaba combinar dos líneas (para un procesamiento más fácil), pero permitía que los datos pasasen el específico, encontré que esto era útil

data.txt

string1=x string2=y string3 string4

cat data.txt | nawk ''$ 0 ~ / string1 = / {printf "% s", $ 0; obtener línea; printf "% s / n", $ 0; getline} {print} ''> converted_data.txt

La salida se ve así:

convert_data.txt

string1=x string2=y string3 string4


Hay más formas de matar a un perro que colgando. [1]

awk ''{key=$0; getline; print key ", " $0;}''

Pon el delimitador que quieras dentro de las comillas.

Referencias

  1. Originalmente "Muchas formas de desollar al gato", revertido a una expresión más antigua y potencialmente originaria que tampoco tiene nada que ver con las mascotas.

La forma más simple está aquí:

  1. Elimine las líneas pares y escríbalas en algún archivo temporal 1.
  2. Elimine las líneas impares y escríbalas en algún archivo temporal 2.
  3. Combina dos archivos en uno usando el comando pegar con -d (significa eliminar espacio)

sed ''0~2d'' file > 1 && sed ''1~2d'' file > 2 && paste -d " " 1 2


Otra solución que usa vim (solo como referencia).

Solución 1 :

Abra el archivo en el vim filename archivo vim vim filename , luego ejecute el comando :% normal Jj

Este comando es fácil de entender:

  • %: para todas las líneas,
  • normal: ejecuta el comando normal
  • Jj: ejecuta el comando Unir, luego salta a la línea inferior

Después de eso, guarde el archivo y salga con :wq

Solución 2 :

Ejecute el comando en shell, vim -c ":% normal Jj" filename , luego guarde el archivo y salga con :wq .


Pruebe la siguiente línea:

while read line1; do read line2; echo "$line1 $line2"; done <old.txt>new_file

Poner delimitador en el medio

"$line1 $line2";

por ejemplo, si el delimitador es | , entonces:

"$line1|$line2";


Puedes usar xargs así:

xargs -a file


Puedes usar awk como este para combinar 2 pares de líneas:

awk ''{ if (NR%2 != 0) line=$0; else {printf("%s %s/n", line, $0); line="";} } / END {if (length(line)) print line;}'' flle


Si Perl es una opción, puede intentar:

perl -0pe ''s/(.*)/n(.*)/n/$1 $2/n/g'' file.txt


También puede usar el siguiente comando vi:

:%g/.*/j


Una ligera variación en la respuesta de glenn jackman usando paste : si el valor para la opción de delimitador -d contiene más de un carácter, paste cíclicamente los caracteres uno por uno, y combinado con las opciones -s sigue haciéndolo mientras procesa el mismo archivo de entrada .

Esto significa que podemos usar lo que queramos tener como separador más la secuencia de escape /n para unir dos líneas a la vez.

Usando una coma:

$ paste -s -d '',/n'' infile KEY 4048:1736 string,3 KEY 0:1772 string,1 KEY 4192:1349 string,1 KEY 7329:2407 string,2 KEY 0:1774 string,1

y el signo de dólar:

$ paste -s -d ''$/n'' infile KEY 4048:1736 string$3 KEY 0:1772 string$1 KEY 4192:1349 string$1 KEY 7329:2407 string$2 KEY 0:1774 string$1

Lo que no se puede hacer es usar un separador que consta de varios caracteres.

Como extra, si la paste cumple con POSIX, esto no modificará la nueva línea de la última línea del archivo, por lo que para un archivo de entrada con un número impar de líneas como

KEY 4048:1736 string 3 KEY 0:1772 string

paste no paste en el carácter de separación en la última línea:

$ paste -s -d '',/n'' infile KEY 4048:1736 string,3 KEY 0:1772 string


Una solución más general (permite unir más de una línea de seguimiento) como un script de shell. Esto agrega una línea entre cada uno, porque necesitaba visibilidad, pero eso se remedia fácilmente. Este ejemplo es donde la línea "clave" terminó en: y ninguna otra línea lo hizo.

#!/bin/bash # # join "The rest of the story" when the first line of each story # matches $PATTERN # Nice for looking for specific changes in bart output # PATTERN=''*:''; LINEOUT="" while read line; do case $line in $PATTERN) echo "" echo $LINEOUT LINEOUT="$line" ;; "") LINEOUT="" echo "" ;; *) LINEOUT="$LINEOUT $line" ;; esac done


awk:

awk ''NR%2{printf "%s ",$0;next;}1'' yourFile

nota, hay una línea vacía al final de la salida.

sed:

sed ''N;s//n/ /'' yourFile


paste es bueno para este trabajo:

paste -d " " - - < filename


nawk ''$0 ~ /string$/ {printf "%s ",$0; getline; printf "%s/n", $0}'' filename

Esto se lee como

$0 ~ /string$/ ## matches any lines that end with the word string printf ## so print the first line without newline getline ## get the next line printf "%s/n" ## print the whole line and carriage return


perl -0pE ''s{^KEY.*?/K/s+(/d+)$}{ $1}msg;'' data.txt > data_merged-lines.txt

-0 engulle todo el archivo en lugar de leerlo línea por línea;
pE ajusta el código con loop e imprime el resultado, consulte los detalles en http://perldoc.perl.org/perlrun.html ;
^KEY coincida con "KEY" en el comienzo de la línea, seguido de una coincidencia no codiciosa de cualquier cosa ( .*? ) Antes de la secuencia de

  1. uno o más espacios /s+ de cualquier tipo, incluidos los saltos de línea;
  2. uno o más dígitos (/d+) que capturamos y luego reinsertamos como $1 ;

seguido por el final de la línea $ .

/K convenientemente excluye todo lo que está a su izquierda de la sustitución, por lo que { $1} reemplaza solo una o dos secuencias, consulte http://perldoc.perl.org/perlre.html .