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
,sed
ypure bash
! (xargs
es 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
printf
cadenas de expansión como%s
dentro$0
. Ese fracaso puede evitarse así:'NR%2{printf "%s ",$0;next;}1'
1
después de la llave de cierre?paste
es bueno para este trabajo:fuente
paste
, por otro lado, se comporta perfectamente. +1.cut
pero 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 -n2
que se separa en palabras en lugar de líneas.-d
se puede usar para dividir la entrada por cualquier carácter individual.fuente
-d '\n'
xargs
usuario 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
. Elgetline
comando 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 variablekey
con 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 elp
al final?/KEY/
búsquedas de la línea con elKEY
. elp
imprime 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.
ORS
significa Separador de registro de salida. Lo que estamos haciendo aquí es probar una condición usando laNR
que almacena el número de línea. Si el módulo deNR
es 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
ORS
y se trata como sitrue
ORS 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
-0
Le 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 Jj
Este comando es muy fácil de entender:
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
.fuente
norm!
más robusto quenormal
en caso deJ
ser reasignado. +1 para la solución vim.También puede usar el siguiente comando vi:
fuente
:%g//j
dado 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-d
opción delimitador contiene más de un carácter,paste
recorre los caracteres uno por uno, y combinado con las-s
opciones 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 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
paste
beneficio 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 comopaste
no 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
-0
engulle todo el archivo en lugar de leerlo línea por línea;pE
envuelve el código con el bucle e imprime la salida, consulte los detalles en http://perldoc.perl.org/perlrun.html ;^KEY
coincide 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
$
.\K
excluye 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
xargs
así:fuente
xargs -n 2
pero esta respuesta no explica esto en absoluto.