Quiero unir varias líneas en un archivo según un patrón que comparten ambas líneas.
Este es mi ejemplo:
{101}{}{Apples}
{102}{}{Eggs}
{103}{}{Beans}
{104}...
...
{1101}{}{This is a fruit.}
{1102}{}{These things are oval.}
{1103}{}{You have to roast them.}
{1104}...
...
Quiero unirme a las líneas {101}{}{Apples}
y{1101}{}{This is a fruit.}
a una línea {101}{}{Apples}{1101}{}{This is a fruit.}
para su posterior procesamiento.
Lo mismo ocurre con las otras líneas.
Como puede ver, ambas líneas comparten el número 101, pero no tengo idea de cómo lograrlo. ¿Algunas ideas?
/EDITAR:
Encontré una "solución alternativa":
Primero, elimine todos los caracteres "{1" anteriores del grupo dos en el modo VISUAL BLOCK con C-V
(o un atajo similar), luego ordene todas las líneas por número con :%sort n
y luego una cada segunda línea con :let @q = "Jj"
seguido de 500@q
.
Esto funciona, pero me deja con {101}{}{Apples} 101}{}{This is a fruit.}
. Luego necesitaría agregar los caracteres faltantes "{1" en cada línea, lo que no es exactamente lo que quiero. Cualquier ayuda se agradece.
Respuesta1
En lugar de eliminar el {1
, simplemente hazlo.
:%sort rn /\d\d\d}/
Eso hará una clasificación numérica, pero en cada línea solo verá tres dígitos seguidos de }.
Además, para unir las líneas después, haría
:g/{\d\d\d}/j!
Respuesta2
Aquí hay una manera de hacerlo en el shell con un archivo:
join -j 2 \
<(sed -n '/^{...}/{s/{/{ /;s/}/ }/;p}' inputfile) \
<(sed -n '/^{....}/{s/{./& /;s/}/ }/;p}' inputfile) |
sed 's/^\([^ ]*\) { }{}\({[^}]*}\) {1 }\({.*}\)$/{\1}{}\2{1\1}\3/'
Utiliza las dos primeras invocaciones de sed
para dividir el archivo según el número de dígitos entre el primer conjunto de llaves y agrega espacios alrededor de los últimos tres dígitos ( {101}
se convierte { 101 }
y {1101}
se convierte {1 101 }
). Luego usa esos números de tres dígitos como campo para join
activar la tecla de comando. El último sed
comando devuelve los dígitos a su lugar y elimina los espacios adicionales agregados anteriormente.
Un vim
gurú probablemente podría hacer algo mejor en su interior vim
. Podría hacer algo más sencillo que lo anterior usando AWK.
Respuesta3
A continuación se muestra un ejemplo de uso del editor Vim/Ex desde la línea de comandos para un patrón:
$ ex +'redir @a|sil g/101}/' +'redi>>/dev/stdout|echon join(split(@a),"")' -scq! input.txt
{101}{}{Apples}{1101}{}{This is a fruit.}
Para patrones múltiples, repita con comandos adicionales, agregue un bucle o realice un bucle desde el shell, por ejemplo
$ for i in `seq 1 3`; do ex +"redir @a|sil g/10$i}/" +'redi>>/dev/stdout|echo join(split(@a),"")' -scq! input.txt; done
{101}{}{Apples}{1101}{}{Thisisafruit.}
{102}{}{Eggs}{1102}{}{Thesethingsareoval.}
{103}{}{Beans}{1103}{}{Youhavetoroastthem.}
Usar solo Shell para analizar los datos es mucho más simple, por ejemplo:
$ grep "101}" input.txt | xargs
{101}{}{Apples} {1101}{}{This is a fruit.}
Para varias líneas:
$ for i in `seq 1 4`; do grep "10$i}" input.txt | xargs; done
{101}{}{Apples} {1101}{}{This is a fruit.}
{102}{}{Eggs} {1102}{}{These things are oval.}
{103}{}{Beans} {1103}{}{You have to roast them.}