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 fusiono dos líneas en una?

pr,paste,awk,xargs,sedypure bash! (xargses el más lento, más lento que bash !)Respuestas:
awk:
tenga en cuenta que hay una línea vacía al final de la salida.
sed:
fuente
printfcadenas de expansión como%sdentro$0. Ese fracaso puede evitarse así:'NR%2{printf "%s ",$0;next;}1'1después de la llave de cierre?pastees bueno para este trabajo:fuente
paste, por otro lado, se comporta perfectamente. +1.cutpero siempre me olvidopaste. Es genial para este problema. Necesitaba combinar todas las líneas de stdin y lo hice fácilmentepaste -sd ' ' -.-malo stdin, tanpaste - -malo leer de stdin, luego leer de stdin, puedes apilar tantos como quieras, espero.Alternativa a sed, awk, grep:
Esto es mejor cuando desea unir N líneas y solo necesita una salida delimitada por espacios.
Mi respuesta original fue
xargs -n2que se separa en palabras en lugar de líneas.-dse puede usar para dividir la entrada por cualquier carácter individual.fuente
-d '\n'xargsusuario habitual pero no lo sabía. Gran consejoHay más formas de matar a un perro que colgando. [1]
Ponga el delimitador que desee dentro de las comillas.
Referencias
fuente
$0. Elgetlinecomando también toma "la siguiente" línea de entrada y la coloca$0. Entonces, la primera instrucción toma la primera línea, y el comando de impresión concatena lo que se guardó en la variablekeycon una cadena que contiene una coma, junto con la línea que se obtuvo usandogetline. Más claro? :)Aquí está mi solución en bash:
fuente
Aunque parece que las soluciones anteriores funcionarían, si ocurre una sola anomalía en el documento, la salida se partiría en pedazos. A continuación se muestra un poco más seguro.
fuente
/KEY/hacer? ¿Qué hace elpal final?/KEY/búsquedas de la línea con elKEY. elpimprime el resultado. es más seguro porque solo aplica la operación en líneas con unKEY.Aquí hay otra forma con
awk:Como lo indicó Ed Morton en los comentarios, es mejor agregar llaves para mayor seguridad y parens para portabilidad.
ORSsignifica Separador de registro de salida. Lo que estamos haciendo aquí es probar una condición usando laNRque almacena el número de línea. Si el módulo deNRes un valor verdadero (> 0), establecemos el Separador de campo de salida en el valor deFS(Separador de campo) que, de forma predeterminada, es espacio; de lo contrario, asignamos el valor deRS(Separador de registro) que es nueva línea.Si desea agregar
,como separador, utilice lo siguiente:fuente
ORSy se trata como sitrueORS obtiene un valor que no es cero o una cadena nula y se despierta adivinando correctamente que debería ser una picadura en lugar de una comparación numérica? ¿Es algo más? Realmente no estoy seguro, así que lo habría escrito comoawk '{ORS=(NR%2?FS:RS)}1' file. Puse entre paréntesis la expresión ternaria para garantizar la portabilidad también."ex" es un editor de línea programable que pertenece a la misma familia que sed, awk, grep, etc. Creo que podría ser lo que estás buscando. Muchos clones / sucesores vi modernos también tienen un modo vi.
Esto dice para cada línea, si coincide con "CLAVE", realice un j oin de la siguiente línea. Después de que complete el mandato (en contra de todas las líneas), emitir una w rito y q uit.
fuente
Si Perl es una opción, puedes probar:
fuente
-0Le dice a Perl que establezca el separador de registros ($/)en nulo, para que podamos abarcar varias líneas en nuestro patrón de coincidencia. Las páginas de manual son un poco demasiado técnicas para que yo pueda entender lo que significa en la práctica.Puede usar awk como este para combinar cada 2 pares de líneas:
fuente
Otras soluciones que usan vim (solo como referencia).
Solución 1 :
Abra el archivo en vim
vim filename, luego ejecute el comando:% normal JjEste comando es muy fácil de entender:
Después de eso, guarde el archivo y salga con
:wqSolución 2 :
Ejecute el comando en shell,
vim -c ":% normal Jj" filenameluego guarde el archivo y salga con:wq.fuente
norm!más robusto quenormalen caso deJser reasignado. +1 para la solución vim.También puede usar el siguiente comando vi:
fuente
:%g//jdado que todo lo que necesita es una coincidencia para que se ejecute la unión , y una cadena nula sigue siendo una expresión regular válida.//, se usará el patrón de búsqueda anterior. Si no hay un patrón anterior, Vim simplemente informa un error y no hace nada. La solución de Jdamian funciona todo el tiempo.Una ligera variación en la respuesta de glenn jackman usando
paste: si el valor de la-dopción delimitador contiene más de un carácter,pasterecorre los caracteres uno por uno, y combinado con las-sopciones 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
\npara fusionar dos líneas a la vez.Usando una coma:
y el signo de dólar:
Lo que esto no puede hacer es usar un separador que consta de varios caracteres.
Como
pastebeneficio adicional, si es compatible 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 comopasteno agregará el carácter de separación en la última línea:fuente
Esto se lee como
fuente
En el caso donde necesitaba combinar dos líneas (para un procesamiento más fácil), pero permitir que los datos pasen los específicos, encontré que esto es útil
data.txt
la salida se ve así:
convert_data.txt
fuente
Otro enfoque con vim sería:
Esto aplica un
join(a la línea debajo de él) a todas las líneas que tienen la palabraKEY. Resultado:fuente
La manera más simple es aquí:
fuente
-0engulle todo el archivo en lugar de leerlo línea por línea;pEenvuelve el código con el bucle e imprime la salida, consulte los detalles en http://perldoc.perl.org/perlrun.html ;^KEYcoincide con "KEY" al comienzo de la línea, seguido de una coincidencia no codiciosa de nada (.*?) antes de la secuencia de\s+de cualquier tipo, incluidos los saltos de línea;(\d+)que capturamos y luego volvemos a insertar como$1;seguido por el final de la línea
$.\Kexcluye convenientemente todo en su lado izquierdo de la sustitución, por lo que{ $1}reemplaza solo la secuencia 1-2, consulte http://perldoc.perl.org/perlre.html .fuente
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 soluciona fácilmente. Este ejemplo es donde terminó la línea "clave": y ninguna otra línea lo hizo.
fuente
Pruebe la siguiente línea:
Poner delimitador en el medio
por ejemplo, si el delimitador es
|, entonces:fuente
Puedes usar
xargsasí:fuente
xargs -n 2pero esta respuesta no explica esto en absoluto.