¿Cómo puedo eliminar todo el texto después de un personaje en bash?

147

¿Cómo puedo eliminar todo el texto después de un carácter, en este caso dos puntos (":"), en bash? ¿Puedo quitar el colon también? No tengo idea de cómo hacerlo.

Nathan
fuente

Respuestas:

135

Un ejemplo podría haber sido útil, pero si te entendiera correctamente, esto funcionaría:

echo "Hello: world" | cut -f1 -d":"

Esto convertirá "hola: mundo" en "hola".

Eldad Mor
fuente
55
cutfunciona, pero la respuesta de Dennis es mejor y más flexible. ¿Alguien sabe si genera un nuevo proceso como cut?
JoBu1324
3
Es mejor usar las funciones de expansión de parámetros incorporadas de Bash que generar herramientas de ejecución de subshells como basenamey cut, vea la respuesta de Dennis a continuación
Louis Maddox
1
cutpuede leer desde stdin, por lo que es mejor especialmente cuando tiene una cadena muy larga que necesita procesar, como el contenido de un archivo.
Sahas
1
¿Y cómo se aplicaría esto hello: world? Esta es la mitad de una respuesta.
K - La toxicidad en SO está creciendo.
Se puede hacer usando la sintaxis de sustitución también como {var /: / ''}, pero solo funciona en bash ..
Mahesh
265

En Bash (y ksh, zsh, dash, etc.), puede usar la expansión de parámetros con la %que eliminará caracteres del final de la cadena o #que eliminará caracteres del principio de la cadena. Si usa uno solo de esos caracteres, se eliminará la cadena coincidente más pequeña. Si dobla el personaje, se eliminará el más largo.

$ a='hello:world'
$ b=${a%:*}
$ echo "$b"
hello
$ a='hello:world:of:tomorrow'
$ echo "${a%:*}"
hello:world:of
$ echo "${a%%:*}"
hello
$ echo "${a#*:}"
world:of:tomorrow
$ echo "${a##*:}"
tomorrow
Pausado hasta nuevo aviso.
fuente
66
Esta es una manipulación de cadena de shell nativa, por lo que no se generarán procesos adicionales. Sustitución de parámetros de referencia de Bash , manipulación de cadenas de Bash y mejores secuencias de comandos de Bash
Dodzi Dzakuma
@denniswilliamson ¿Cómo podría eliminar 2 caracteres después de hello:worldque se hello:wouse una cadena específica como ${a%:*}?
3kstc
Gran respuesta, muchas gracias, pero será bueno agregar también "${a##*:}"para obtener solo tomorrow=)
avtomaton
1
@openCivilisation: es probable que necesite usar expresiones regulares continuación: a='hello:world:of:tomorrow'; pattern=''^([^:]*:).*$'; [[$ a = ~ $ patrón]]; echo "$ {BASH_REMATCH [1]}" `. Eso coincide solo si hay dos puntos. Si desea que eso sea opcional, se tendría que usar un patrón diferente. Una explicación de las expresiones regulares de Bash (y las expresiones regulares en general) está más allá del alcance de estos comentarios. Puede encontrar otras preguntas que analicen esto o publique las suyas.
Pausado hasta nuevo aviso.
1
@ kp123: es el primer ejemplo en mi respuesta. La segunda vez que lo muestro (donde se elimina "mañana"), es casi exactamente la situación sobre la que estás preguntando.
En pausa hasta nuevo aviso.
9
$ echo 'hello:world:again' |sed 's/:.*//'
hello
sk8asd123
fuente
4
egrep -o '^[^:]*:'
cdhowie
fuente
¿Puedes explicar cómo interpretar esto? Gracias.
rɑːdʒɑ
1
egrepes grep con -E. No hace diferencia aquí de regular grep. -oindica a grep que imprima solo la parte de la línea que coincide con la expresión. ^ancla el partido al inicio de una línea. [^:]*coincide con cero o más caracteres que no son el :carácter. :coincide con el carácter :.
cdhowie
Gracias de nuevo por la explicación
rɑːdʒɑ
3

Digamos que tiene una ruta con un archivo en este formato:

/dirA/dirB/dirC/filename.file

Ahora solo desea la ruta que incluye cuatro "/". Tipo

$ echo "/dirA/dirB/dirC/filename.file" | cut -f1-4 -d"/"

y tu salida será

/dirA/dirB/dirC

La ventaja de usar cut es que también puede cortar el directorio superior así como el archivo (en este ejemplo), así que si escribe

$ echo "/dirA/dirB/dirC/filename.file" | cut -f1-3 -d"/"

su salida sería

/dirA/dirB

Aunque puede hacer lo mismo desde el otro lado de la cadena, en este caso no tendría tanto sentido como escribir

$ echo "/dirA/dirB/dirC/filename.file" | cut -f2-4 -d"/"

resultados en

dirA/dirB/dirC

En algunos otros casos, el último caso también podría ser útil. Tenga en cuenta que no hay "/" al comienzo de la última salida.

Nico Feulner
fuente
2
¿Qué sucede si tiene un directorio "/resources/views/admin/users/relationships/posts.blade.php" y desea truncar todo después de la ÚLTIMA aparición de "/", dado que NO sabe cuántos "/ "los caracteres están en la cadena. Así que aquí me gustaría que la salida sea "/ resources / views / admin / users / relations /" (o incluso / resources / views / admin / users / relations sin la barra inclinada final). ¿Cómo lo harías tú?
kp123
-1

recortar todo después de la última instancia de ":"

cat fileListingPathsAndFiles.txt | grep -o '^.*:'

y si quisieras soltar ese último ":"

cat file.txt | grep -o '^.*:' | sed 's/:$//'

@ kp123: desea reemplazar :con /(donde debería estar el colon de sed \/)

S Hunter Simpson
fuente