@ruakh, ¿cómo escribo esta declaración con una condición o? Solo si quiero reemplazar a Suzi o Marry con una nueva cadena.
Priyatham51
3
@ Priyatham51: No hay una función incorporada para eso. Simplemente reemplace uno, luego el otro.
ruakh
44
@Bu: No, porque \nen ese contexto se representaría a sí mismo, no a una nueva línea. No tengo Bash útil en este momento para la prueba, pero usted debe ser capaz de escribir algo como: $STRING="${STRING/$'\n'/<br />}". (Aunque probablemente quieras STRING//- reemplazar todo - en lugar de solo STRING/)
ruakh
25
Para ser claros, ya que esto me confundió un poco, la primera parte tiene que ser una referencia variable. No se puede hacer echo ${my string foo/foo/bar}. Necesitaríasinput="my string foo"; echo ${input/foo/bar}
Henrik N
2
@mgutt: esta respuesta enlaza con la documentación relevante. La documentación no es perfecta; por ejemplo, en lugar de mencionar //directamente, menciona lo que sucede "Si el patrón comienza con ' /'" (lo cual ni siquiera es exacto, ya que el resto de esa oración supone que el extra /no es realmente parte de el patrón), pero no conozco ninguna fuente mejor.
Ruakh
208
Esto se puede hacer completamente con la manipulación de cadenas bash:
first="I love Suzy and Mary"
second="Sara"
first=${first/Suzy/$second}
Eso reemplazará solo la primera ocurrencia; para reemplazarlos a todos, doble la primera barra:
first="Suzy, Suzy, Suzy"
second="Sara"
first=${first//Suzy/$second}# first is now "Sara, Sara, Sara"
¿Cuál es el punto de tener una respuesta que duplique la aceptada, en lugar de editar la aceptada con la opción de reemplazo global? Y agregando que las expresiones regulares son compatibles, mientras lo hace. Y explicando qué pasa con "Mala sustitución". Tienes suficientes puntos, @Kevin :)
Dan Dascalescu
66
Parece que ambos respondieron exactamente en el mismo minuto: O
Jamie Hutber
76
Para Dash, todas las publicaciones anteriores no funcionan
La shsolución compatible con POSIX es:
result=$(echo "$firstString"| sed "s/Suzi/$secondString/")
Obtuve esto: $ echo $ (echo $ firstString | sed 's / Suzi / $ secondString / g') Me encanta $ secondString y Casarme
Qstnr_La
2
@Qstnr_La usa comillas dobles para la sustitución de variables:result=$(echo $firstString | sed "s/Suzi/$secondString/g")
emc
1
Además de 1 para mostrar cómo enviar a una variable también. ¡Gracias!
Chef Faraón el
2
Arreglé las comillas simples y también agregué las comillas faltantes alrededor del echoargumento. Funciona engañosamente sin citar con cadenas simples, pero se rompe fácilmente en cualquier cadena de entrada no trivial (espaciado irregular, metacaracteres de shell, etc.).
tripleee
En sh (AWS Codebuild / Ubuntu sh) descubrí que necesito una barra oblicua al final, no una doble. Voy a editar el comentario ya que los comentarios anteriores también muestran una barra inclinada.
En realidad no necesitas Sed para esto; Bash admite este tipo de reemplazo de forma nativa.
ruakh
12
Supongo que esto está etiquetado como "bash" pero vino aquí porque necesitaba algo simple para otro shell. Esta es una buena alternativa sucinta a lo que wiki.ubuntu.com/… hizo que pareciera que lo necesitaría.
natevw
3
Esto funciona muy bien para ash / dash o cualquier otro POSIX sh.
Yoshua Wuyts
2
Me sale el error sed: -e expresión # 1, char 9: opción desconocida para `s
Nam G VU
1
Primera respuesta que funciona con stdin, ideal para canalizar cadenas.
Dinei
46
Es mejor usar bash que sedsi las cadenas tienen caracteres RegExp.
echo ${first_string/Suzi/$second_string}
Es portátil para Windows y funciona con al menos tan antiguo como Bash 3.1.
Para mostrar que no necesita preocuparse demasiado por escapar, cambiemos esto:
/home/name/foo/bar
Dentro de esto:
~/foo/bar
Pero solo si /home/namees al principio. No necesitamos sed!
Dado que bash nos da variables mágicas $PWDy $HOMEpodemos:
echo "${PWD/#$HOME/\~}"
EDITAR: Gracias por Mark Haferkamp en los comentarios por la nota sobre citas / escape ~. *
Observe cómo la variable $HOMEcontiene barras diagonales, pero esto no rompió nada.
Esta respuesta me impidió usar sedel pwdcomando para evitar definir una nueva variable cada vez que se $PS1ejecuta mi personalizado . ¿Bash proporciona una forma más general que las variables mágicas para usar la salida de un comando para el reemplazo de cadenas? En cuanto a su código, tuve que escapar ~para evitar que Bash lo expandiera a $ HOME. Además, ¿qué hace el #comando?
Mark Haferkamp
1
@ MarkHaferkamp Vea esto desde el enlace "lectura adicional recomendada". Sobre "escapar de la ~": observe cómo cité cosas. ¡Recuerda siempre citar cosas! Y esto no solo funciona para las variables mágicas: cualquier variable es capaz de sustituciones, obtener longitud de cadena y más, dentro de bash. Felicidades por intentar tu $PS1ayuno: también te puede interesar $PROMPT_COMMANDsi estás más cómodo con otro lenguaje de programación y quieres codificar un mensaje compilado.
Camilo Martin
El enlace "lectura adicional" explica el "#". En Bash 4.3.30, echo "${PWD/#$HOME/~}"no reemplaza mi $HOMEcon ~. Reemplazar ~con \~o '~'funciona. Cualquiera de estos funciona en Bash 4.2.53 en otra distribución. ¿Puedes actualizar tu publicación para cotizar o escapar ~para una mejor compatibilidad? Lo que quise decir con mi pregunta de "variables mágicas" fue: ¿Puedo usar la sustitución de variables de Bash en, por ejemplo, la salida de unamesin guardarla primero como una variable? En cuanto a mi personal $PROMPT_COMMAND, es complicado .
Mark Haferkamp
@ MarkHaferkamp Whoa, tienes toda la razón, mi mal. Actualizará la respuesta ahora.
Camilo Martin
1
@MarkHaferkamp Bash y sus peligros oscuros ...: P
Camilo Martin
19
Si mañana decides que no amas a Marry, ella también puede ser reemplazada:
Como no puedo agregar un comentario. @ruaka Para que el ejemplo sea más legible, escríbalo así
full_string="I love Suzy and Mary"
search_string="Suzy"
replace_string="Sara"
my_string=${full_string/$search_string/$replace_string}
or
my_string=${full_string/Suzy/Sarah}
Hasta que llegué a su ejemplo, había entendido el orden al revés. Esto ayudó a aclarar lo que está sucediendo
raghav710
5
Pura POSIX método de cáscara, que a diferencia de Romano Kazanovskyi 's sedrespuesta basada no necesita herramientas externas, sólo propios nativos de la concha Expansiones de parámetros . Tenga en cuenta que los nombres largos de archivo se minimizan para que el código se ajuste mejor en una línea:
f="I love Suzi and Marry"
s=Sara
t=Suzi["${f%$t*}"!="$f"]&& f="${f%$t*}$s${f#*$t}"
echo "$f"
Salida:
I love Sara and Marry
Cómo funciona:
Eliminar el patrón de sufijo más pequeño. "${f%$t*}"devuelve " I love" si el sufijo $t" Suzi*" está en $f" ". I loveSuzi and Marry
Pero si t=Zelda, entonces "${f%$t*}"no elimina nada y devuelve toda la cadena " I love Suzi and Marry".
Esto se utiliza para probar si $testá dentro $fde lo [ "${f%$t*}" != "$f" ]cual se evaluará como verdadero si la $fcadena contiene " Suzi*" y falso si no.
Si la prueba devuelve verdadero , construya la cadena deseada usando Eliminar patrón de sufijo más pequeño${f%$t*} " I love" y Eliminar patrón de prefijo más pequeño${f#*$t} " and Marry", con la segunda cadena $s" Sara" en el medio.
Respuestas:
Para reemplazar la primera aparición de un patrón con una cadena dada, use :
${parameter/pattern/string}
Para reemplazar todas las ocurrencias, use :
${parameter//pattern/string}
(Esto está documentado en el Manual de referencia de Bash , §3.5.3 "Expansión de parámetros de shell" ).
Tenga en cuenta que POSIX no especifica esta característica, es una extensión Bash, por lo que no todos los shells de Unix la implementan. Para obtener la documentación relevante de POSIX, consulte las especificaciones básicas de la norma técnica de Open Group, número 7 , el volumen Shell y utilidades , §2.6.2 "Expansión de parámetros" .
fuente
\n
en ese contexto se representaría a sí mismo, no a una nueva línea. No tengo Bash útil en este momento para la prueba, pero usted debe ser capaz de escribir algo como:$STRING="${STRING/$'\n'/<br />}"
. (Aunque probablemente quierasSTRING//
- reemplazar todo - en lugar de soloSTRING/
)echo ${my string foo/foo/bar}
. Necesitaríasinput="my string foo"; echo ${input/foo/bar}
//
directamente, menciona lo que sucede "Si el patrón comienza con '/
'" (lo cual ni siquiera es exacto, ya que el resto de esa oración supone que el extra/
no es realmente parte de el patrón), pero no conozco ninguna fuente mejor.Esto se puede hacer completamente con la manipulación de cadenas bash:
Eso reemplazará solo la primera ocurrencia; para reemplazarlos a todos, doble la primera barra:
fuente
Para Dash, todas las publicaciones anteriores no funcionan
La
sh
solución compatible con POSIX es:fuente
result=$(echo $firstString | sed "s/Suzi/$secondString/g")
echo
argumento. Funciona engañosamente sin citar con cadenas simples, pero se rompe fácilmente en cualquier cadena de entrada no trivial (espaciado irregular, metacaracteres de shell, etc.).prueba esto:
fuente
Es mejor usar bash que
sed
si las cadenas tienen caracteres RegExp.Es portátil para Windows y funciona con al menos tan antiguo como Bash 3.1.
Para mostrar que no necesita preocuparse demasiado por escapar, cambiemos esto:
Dentro de esto:
Pero solo si
/home/name
es al principio. No necesitamossed
!Dado que bash nos da variables mágicas
$PWD
y$HOME
podemos:EDITAR: Gracias por Mark Haferkamp en los comentarios por la nota sobre citas / escape
~
. *Observe cómo la variable
$HOME
contiene barras diagonales, pero esto no rompió nada.Lectura adicional: Guía avanzada de secuencias de comandos Bash .
Si usar
sed
es imprescindible, asegúrate de escapar de todos los personajes .fuente
sed
elpwd
comando para evitar definir una nueva variable cada vez que se$PS1
ejecuta mi personalizado . ¿Bash proporciona una forma más general que las variables mágicas para usar la salida de un comando para el reemplazo de cadenas? En cuanto a su código, tuve que escapar~
para evitar que Bash lo expandiera a $ HOME. Además, ¿qué hace el#
comando?~
": observe cómo cité cosas. ¡Recuerda siempre citar cosas! Y esto no solo funciona para las variables mágicas: cualquier variable es capaz de sustituciones, obtener longitud de cadena y más, dentro de bash. Felicidades por intentar tu$PS1
ayuno: también te puede interesar$PROMPT_COMMAND
si estás más cómodo con otro lenguaje de programación y quieres codificar un mensaje compilado.echo "${PWD/#$HOME/~}"
no reemplaza mi$HOME
con~
. Reemplazar~
con\~
o'~'
funciona. Cualquiera de estos funciona en Bash 4.2.53 en otra distribución. ¿Puedes actualizar tu publicación para cotizar o escapar~
para una mejor compatibilidad? Lo que quise decir con mi pregunta de "variables mágicas" fue: ¿Puedo usar la sustitución de variables de Bash en, por ejemplo, la salida deuname
sin guardarla primero como una variable? En cuanto a mi personal$PROMPT_COMMAND
, es complicado .Si mañana decides que no amas a Marry, ella también puede ser reemplazada:
Debe haber 50 formas de dejar a tu amante.
fuente
Como no puedo agregar un comentario. @ruaka Para que el ejemplo sea más legible, escríbalo así
fuente
Pura POSIX método de cáscara, que a diferencia de Romano Kazanovskyi 's
sed
respuesta basada no necesita herramientas externas, sólo propios nativos de la concha Expansiones de parámetros . Tenga en cuenta que los nombres largos de archivo se minimizan para que el código se ajuste mejor en una línea:Salida:
Cómo funciona:
Eliminar el patrón de sufijo más pequeño.
"${f%$t*}"
devuelve "I love
" si el sufijo$t
"Suzi*
" está en$f
" ".I love
Suzi and Marry
Pero si
t=Zelda
, entonces"${f%$t*}"
no elimina nada y devuelve toda la cadena "I love Suzi and Marry
".Esto se utiliza para probar si
$t
está dentro$f
de lo[ "${f%$t*}" != "$f" ]
cual se evaluará como verdadero si la$f
cadena contiene "Suzi*
" y falso si no.Si la prueba devuelve verdadero , construya la cadena deseada usando Eliminar patrón de sufijo más pequeño
${f%$t*}
"I love
" y Eliminar patrón de prefijo más pequeño${f#*$t}
"and Marry
", con la segunda cadena$s
"Sara
" en el medio.fuente
Sé que esto es viejo, pero como nadie mencionó el uso de awk:
fuente
fuente