Tengo un archivo que tiene un montón de nombres de host correlacionados con IP que se ve así:
x-cluster-front-1 192.168.1.2
x-cluster-front-2 192.158.1.10
y-cluster-back-1 10.1.11.99
y-cluster-back-2 10.1.157.38
int.test.example.com 59.2.86.3
super.awesome.machine 123.234.15.6
Quiero que se vea así:
x-cluster-front-1 192.168.1.2
x-cluster-front-2 192.158.1.10
y-cluster-back-1 10.1.11.99
y-cluster-back-2 10.1.157.38
int-test-example-com 59.2.86.3
super-awesome-machine 123.234.15.6
¿Cómo puedo reemplazar el. (puntos) de la primera columna con - (guión) para facilitar una ordenación por la segunda columna? Estaba pensando en usar sed para reemplazar los puntos hasta el primer espacio, o reemplazar cada punto excepto los últimos tres, pero tengo problemas para entender regex y sed. ¡Puedo realizar reemplazos simples pero esto está muy por encima de mi cabeza!
Esto es parte de un script más grande que he estado escribiendo en bash. Estoy atrapado en esta parte.

awkse basa ennawk, por lo que todas lasawkimplementaciones modernas deberían tenergsub. En Solaris, puede necesitar/usr/xpg4/bin/awkonawk.Si necesita hacer las sustituciones en el primer campo, lo mejor es usar la solución awk de Rahul, pero tenga en cuenta que puede afectar el espacio (los campos se reescriben con un solo espacio entre ellos).
Puede evitarlo escribiéndolo en su lugar:
La
-pbandera significa "leer el archivo de entrada línea por línea e imprimir cada línea después de aplicar el script dado por-e". Entonces, el sustituto de (s|pattern|replacement|) la primera secuencia de caracteres no espaciales (\S+) con el patrón emparejado ($&) después de sustituir todo.con-. El truco es usars|||edonde eleoperador evaluará una expresión como reemplazo. Por lo tanto, puede tener un reemplazo (tr/./-/) aplicado a la coincidencia ($&) del anterior (s|||e).Si necesita sustituir cada uno
.con un-excepto los últimos 3 últimos, con GNUsedy suponiendo que tiene unrevcomando:fuente
/rque funcione).Sed no es la herramienta más fácil para el trabajo; vea otras respuestas para obtener mejores herramientas, pero se puede hacer.
Para reemplazar
.por-sólo hasta el primer espacio, el usosen un bucle.(Tenga en cuenta que algunas implementaciones de sed no admiten comentarios en la misma línea. GNU sed sí lo hace).
Para realizar el reemplazo hasta el último espacio:
Otra técnica hace uso del espacio de retención de sed. Guarde el bit que no desea modificar en el espacio de espera, haga su trabajo, luego recupere el espacio de espera. Aquí, divido la línea en el último espacio y reemplazo los puntos por guiones en la primera parte.
fuente
Dado que Rahul le dio la respuesta canónica para su caso de uso, pensé en intentar responder al problema titular: sustituir todas las ocurrencias x, excepto las últimas, de una expresión regular:
El código anterior (probado) no supone que tenga campos separados por espacios. Reemplazará todos los puntos en una línea con guiones, excepto los últimos 3 puntos. Reemplace el
3en el código a su gusto.fuente
Puede usar muchas herramientas diferentes para esto. Rahul Patil ya te dio
gawkuno, así que aquí hay algunos otros:perl
El
-ainterruptor hace que Perl divida automáticamente las líneas de entrada en el espacio en blanco y guarde los campos resultantes en la matriz@F. El primer campo, por lo tanto, será$F[0]así que reemplazamos (s///) todas las apariciones de.with-en el primer campo y luego imprimimos toda la matriz.cáscara
Aquí, el bucle while lee el archivo y se divide automáticamente en espacios en blanco. Esto crea dos campos
$firsty$rest. La construcción${first//pattern/replacement}reemplaza todas las ocurrencias depatternconreplacement.fuente
perlrun(1)le diré que-aes "modo de división automática", prefiero pensar en él como "awkmodo": DCreo que esto es un poco más fácil de leer que una gran expresión regular desagradable. Básicamente, simplemente dividí la línea en dos campos en el espacio en blanco y utilicé sed en la primera parte.
Dependiendo de su shell, también podría usar $ {host //./-} en lugar del comando sed.
fuente
Sin usar
gal final del comando puede hacer esto ... Esto simplemente reemplazará la primera aparición del patrónfuente