Tengo dos archivos paralelos con el mismo número de líneas en dos idiomas y planeo fusionar estos dos archivos línea por línea con el delimitador |||
. Por ejemplo, los dos archivos son los siguientes:
Presentar un:
1Mo 1,1 I love you.
1Mo 1,2 I like you.
Hi 1,3 I am hungry.
Hi 1,4 I am foolish.
Archivo B:
1Mo 1,1 Ich liebe dich.
1Mo 1,2 Ich mag dich.
Hi 1,3 Ich habe Durst.
Hi 1,4 Ich bin neu.
El resultado esperado es así:
1Mo 1,1 I love you. ||| 1Mo 1,1 Ich liebe dich.
1Mo 1,2 I like you. ||| 1Mo 1,2 Ich mag dich.
Hi 1,3 I am hungry. ||| Hi 1,3 Ich habe Durst.
Hi 1,4 I am foolish. ||| Hi 1,4 Ich bin neu.
Probé el paste
comando como:
paste -d "|||" fileA fileB
Pero la salida devuelta solo contiene una tubería como:
1Mo 1,1 I love you. |1Mo 1,1 Ich liebe dich.
1Mo 1,2 I like you. |1Mo 1,2 Ich mag dich.
¿Hay alguna manera de separar cada par de líneas por tubería tripa |||
?
text-processing
sed
awk
Fruncir el ceño
fuente
fuente
paste -d '|||' fileA - - fileB < /dev/null
Respuestas:
Con pasta POSIX :
paste
concatenará las líneas correspondientes de todos los archivos de entrada. Aquí tenemos seis archivos,fileA
cuatro archivos ficticios de entrada estándar-
yfileB
.La lista de delimitadores incluye un espacio, tres tubos y un espacio en ese orden se utilizará
paste
circularmente.Para la primera línea de seis archivos,
fileA
se concatenará con el primer archivo ficticio (que no es nada, gracias al operador no-op :), produceline1-fileA<space>
.El primer archivo ficticio se concatenará con el segundo por una tubería, producir
line1-fileA |
, luego el segundo archivo ficticio con el tercer archivo ficticio, producirline1-fileA ||
, el tercer archivo ficticio con el cuarto archivo ficticio, producirline1-fileA |||
.Y el cuarto archivo ficticio con
fileB
, produceline1-fileA ||| line1-fileB
.Esos pasos se repetirán para todas las líneas y le darán el resultado esperado.
El uso de
:|
es para escribir menos, y se usa principalmente en shell interactivo. En un script, debe usar:para evitar que se genere una subshell.
fuente
:|
. alternativa inteligente a</dev/null
- - - -
, pero la próxima vez incluso puede escribir un par de líneas para explicación :):|paste -d '|' fileA - - fileB
da la versión más correcta sin el delimitador de espacio.Bueno, esto no usa sed, awk o grep, pero puedes hacerlo con bastante facilidad en bash. El comando es:
El problema con pegar es que el delimitador es un solo carácter. También podría insertar un solo carácter y utilizarlo para transformarlo, pero sería propenso a errores si el carácter ya apareciera en el archivo de entrada.
fuente
IFS=
antes de cada unoread
. Puedes hacerlo fácilmente conpaste
. Vea mi respuesta , y también esta para ver por qué debería evitar usar elwhile
bucle en el script de shell.Una versión awk (GNU)
Con el
getline
comando enawk
, puede establecer$0
(todas las variables para columnas) desde el siguiente registro de entrada, sigetline < "filename"
establece el siguiente$0
desde el archivo especificado.¿Por qué su intento no funcionó como esperaba? De
man paste
podemos leerpero usa los delimitadores uno para cada columna .
Entonces el comando
paste -d '|*|*' fileA fileB fileA fileB
me da líneas comoUna
sed
solución que sugiero evitar incluso si está cerca de su intento original, ya que adapta el comportamiento obtenido a su propósito original:Para evitarlo porque sustituye cada patrón
|
con el nuevo|||
, pero debe asumir que el símbolo de tubería (|
) no está presente en sus datos ; de lo contrario, debe tratar casos especiales y hacer que el código sea más complejo para evitar efectos secundarios.Una variante con la cadena Here [ 1 construcción ]
<<<
Establece 5 delimitadores con
-d ' ||| '
(espacio, |, |, |, espacio) y 4 archivos ficticios (- - - -
) que tomarán datos de la cadena vacía''
.Probado en GNU Awk 4.0.1, pegar (GNU coreutils) 8.21 y sed (GNU sed) 4.2.2
fuente
sed
ejemplo para evitar (:-)) y más comentarios.Si desea evitar la magia y el drama de los delimitadores circulares y los archivos ficticios, puede agregar su delimitador a un archivo antes de pegarlos:
da
fuente
puedes hacerlo también en python de esta manera.
fuente