Reemplazar un personaje con otro en Bash

223

Necesito poder hacer es reemplazar un espacio ( ) con un punto ( .) en una cadena en bash.

Creo que esto sería bastante simple, pero soy nuevo, así que no puedo entender cómo modificar un ejemplo similar para este uso.

Brian Leishman
fuente

Respuestas:

390

Utilice el reemplazo de la cadena de la carcasa en línea. Ejemplo:

foo="  "

# replace first blank only
bar=${foo/ /.}

# replace all blanks
bar=${foo// /.}

Consulte http://tldp.org/LDP/abs/html/string-manipulation.html para obtener más detalles.

Brian Clapper
fuente
1
Si bien esta solución es buena cuando se trata de cadenas cortas (el caso común, supongo), uno puede preferir trcadenas largas. En mi sistema trsupera a bash comenzando en cadenas con más de 1000caracteres. Parece que la complejidad del tiempo de bash es peor que lineal. Una pequeña prueba: x="$(tr -dc 'a-z \n' </dev/urandom | head -c1M)"; time y="$(tr ' ' \\- <<< "$x")"; time z="${x// /-}". Con una longitud de cadena de 1M (= 2 ^ 20) trtomó 0.04sy bash 5.0.11 tomó 17s. Con 2M trtomó 0.07s(esperado) pero bash tomó 69s(4 veces más para el doble de la longitud de la cuerda).
Socowi
@Socowi ¡Jugar con 1Mb almacenado en una variable no es realmente habitual! ¡Hasta más de 10Kb, parece que bash se mantiene más rápido que bifurcar tr! ... Dependiendo de la memoria disponible y los recursos de hardware ... ¡Pero tienes razón !: ¡Dependiendo del tipo de trabajo que hacer, las herramientas dedicadas son más eficientes!
F. Hauri
Para los caracteres escapados como las nuevas líneas, asegúrese de buscar$'\n'
user2561747
75

Podrías usar tr, así:

tr " " .

Ejemplo:

# echo "hello world" | tr " " .
hello.world

De man tr:

DESCRIPCIÓN
     Traducir, comprimir y / o eliminar caracteres de la entrada estándar, escribiendo en la salida estándar.

aioobe
fuente
Si bien esto funciona para la pregunta que se hizo, es menos general que la respuesta aceptada (que funciona en el reemplazo de caracteres y también cadenas arbitrarias), y también implica un comando externo.
Dan Dascalescu
2
Por otro lado, funciona en un archivo de 2 gb sin cargar todo en la memoria.
aioobe
La pregunta era sobre "una cadena en bash", no archivos arbitrariamente grandes.
Dan Dascalescu
52

En bash, puede hacer un reemplazo de patrón en una cadena con la ${VARIABLE//PATTERN/REPLACEMENT}construcción. Use solo /y no //para reemplazar solo la primera aparición. El patrón es un patrón comodín, como los globos de archivos.

string='foo bar qux'
one="${string/ /.}"     # sets one to 'foo.bar qux'
all="${string// /.}"    # sets all to 'foo.bar.qux'
Gilles 'SO- deja de ser malvado'
fuente
24

Prueba esto

 echo "hello world" | sed 's/ /./g' 
Robar
fuente
6

Usar sustitución de parámetros:

string=${string// /.}
Fritz G. Mehner
fuente
4

Prueba esto para los caminos:

echo \"hello world\"|sed 's/ /+/g'|sed 's/+/\/g'|sed 's/\"//g'

Reemplaza el espacio dentro de la cadena entre comillas dobles con una +canción, luego reemplaza+ signo con una barra diagonal inversa, luego elimina / reemplaza las comillas dobles.

Tuve que usar esto para reemplazar los espacios en uno de mis caminos en Cygwin.

echo \"$(cygpath -u $JAVA_HOME)\"|sed 's/ /+/g'|sed 's/+/\\/g'|sed 's/\"//g'
dsrdakota
fuente
2
Ya hay una respuesta de dos años que resuelve el problema sed. Las citas son irrelevantes.
chepner