una sustituir script reemplazar manejo extraer especiales eliminar comando caracteres caracter cadenas cadena buscar bash shell string split

sustituir - ¿Cómo dividir una cadena en múltiples cadenas separadas por al menos un espacio en bash shell?



sed linux (7)

¿Intentó simplemente pasar la variable de cadena a un ciclo for ? Bash, por ejemplo, se dividirá en espacios en blanco automáticamente.

sentence="This is a sentence." for word in $sentence do echo $word done

This is a sentence.

Tengo una cadena que contiene muchas palabras con al menos un espacio entre cada dos. ¿Cómo puedo dividir la cadena en palabras individuales para poder recorrerlas?

La cadena se pasa como un argumento. Ej. ${2} == "cat cat file" . ¿Cómo puedo recorrerlo?

Además, ¿cómo puedo verificar si una cadena contiene espacios?


La forma más fácil y segura de BASH 3 y superior es:

var="string to split" read -ra arr <<<"$var"

(donde arr es la matriz que toma las partes divididas de la cadena) o, si puede haber nuevas líneas en la entrada y desea algo más que la primera línea:

var="string to split" read -ra arr -d '''' <<<"$var"

(tenga en cuenta el espacio en -d '''' , no puede dejarse de lado), pero esto podría darle una nueva línea inesperada de <<<"$var" (ya que esto agrega implícitamente una LF al final).

Ejemplo:

touch NOPE var="* a *" read -ra arr <<<"$var" for a in "${arr[@]}"; do echo "[$a]"; done

Resultados lo esperado

[*] [a] [*]

ya que esta solución (a diferencia de todas las soluciones anteriores aquí) no es propensa a englobamiento de shell inesperado ya menudo incontrolable.

También esto le da el poder completo de IFS como probablemente quiera:

Ejemplo:

IFS=: read -ra arr < <(grep "^$USER:" /etc/passwd) for a in "${arr[@]}"; do echo "[$a]"; done

Resultados algo como:

[tino] [x] [1000] [1000] [Valentin Hilbig] [/home/tino] [/bin/bash]

Como puede ver, los espacios se pueden preservar de esta manera también:

IFS=: read -ra arr <<<'' split : this '' for a in "${arr[@]}"; do echo "[$a]"; done

salidas

[ split ] [ this ]

Tenga en cuenta que el manejo de IFS en BASH es un tema por sí mismo, así que haga sus pruebas, algunos temas interesantes sobre esto:

  • unset IFS : Ignora las ejecuciones de SPC, TAB, NL y en línea comienza y termina
  • IFS='''' : Sin separación de campo, simplemente lee todo
  • IFS='' '' : ejecuciones de SPC (y SPC solamente)

Un último ejemplo

var=$''/n/nthis is/n/n/na test/n/n'' IFS=$''/n'' read -ra arr -d '''' <<<"$var" i=0; for a in "${arr[@]}"; do let i++; echo "$i [$a]"; done

salidas

1 [this is] 2 [a test]

mientras

unset IFS var=$''/n/nthis is/n/n/na test/n/n'' read -ra arr -d '''' <<<"$var" i=0; for a in "${arr[@]}"; do let i++; echo "$i [$a]"; done

salidas

1 [this] 2 [is] 3 [a] 4 [test]

Por cierto:

  • Si no está acostumbrado a $''ANSI-ESCAPED-STRING'' , es un ahorro de tiempo.

  • Si no incluye -r (como en read -a arr <<<"$var" ), a continuación, lee se escapa la barra invertida. Esto se deja como ejercicio para el lector.

Para la segunda pregunta:

Para probar algo en una cadena, por lo general me apego a la case , ya que esto puede verificar múltiples casos a la vez (nota: el caso solo ejecuta la primera coincidencia, si necesita usar multiploce las declaraciones de case ), y esta necesidad es muy a menudo el caso (juego de palabras intencionado):

case "$var" in '''') empty_var;; # variable is empty *'' ''*) have_space "$var";; # have SPC *[[:space:]]*) have_whitespace "$var";; # have whitespaces like TAB *[^-+.,A-Za-z0-9]*) have_nonalnum "$var";; # non-alphanum-chars found *[-+.,]*) have_punctuation "$var";; # some punctuation chars found *) default_case "$var";; # if all above does not match esac

Entonces puede establecer el valor de retorno para verificar SPC como este:

case "$var" in (*'' ''*) true;; (*) false;; esac

¿Por qué case ? Porque generalmente es un poco más legible que las secuencias de expresiones regulares, y gracias a los metacaracteres de Shell maneja muy bien el 99% de todas las necesidades.


Me gusta la conversión a una matriz, para poder acceder a elementos individuales:

sentence="this is a story" stringarray=($sentence)

ahora puede acceder a elementos individuales directamente (comienza con 0):

echo ${stringarray[0]}

o convertir de nuevo a cadena para hacer un ciclo:

for i in "${stringarray[@]}" do : # do whatever on $i done

Por supuesto, el bucle de la cadena directamente fue respondido antes, pero esa respuesta tenía la desventaja de no realizar un seguimiento de los elementos individuales para su uso posterior:

for i in $sentence do : # do whatever on $i done

Consulte también Bash Array Reference


Para verificar espacios solo con bash:

[[ "$str" = "${str% *}" ]] && echo "no spaces" || echo "has spaces"


Simplemente use el "set" de proyectiles incorporado. Por ejemplo,

set $text

Después de eso, las palabras individuales en $ text estarán en $ 1, $ 2, $ 3, etc. Para la solidez, uno usualmente lo hace

set -- junk $text shift

para manejar el caso donde $ text está vacío o comienza con un guión. Por ejemplo:

text="This is a test" set -- junk $text shift for word; do echo "[$word]" done

Esto imprime

[This] [is] [a] [test]


(A) Para dividir una oración en sus palabras (espacio separado) puede simplemente usar el IFS predeterminado usando

array=( $string )


Ejemplo que ejecuta el siguiente fragmento

#!/bin/bash sentence="this is the /"sentence/" ''you'' want to split" words=( $sentence ) len="${#words[@]}" echo "words counted: $len" printf "%s/n" "${words[@]}" ## print array

saldrá

words counted: 8 this is the "sentence" ''you'' want to split

Como puede ver, también puede usar comillas simples o dobles sin ningún problema

Notas:
- Esto es básicamente lo mismo que la respuesta de la mob , pero de esta manera almacenas la matriz para cualquier necesidad adicional. Si solo necesita un bucle único, puede usar su respuesta, que es una línea más corta :)
- Consulte esta pregunta para obtener métodos alternativos para dividir una cadena en función del delimitador.


(B) Para buscar un personaje en una cadena, también puede usar una coincidencia de expresión regular.
Ejemplo para verificar la presencia de un carácter de espacio que puede usar:

regex=''/s{1,}'' if [[ "$sentence" =~ $regex ]] then echo "Space here!"; fi


$ echo "This is a sentence." | tr -s " " "/012" This is a sentence.

Para buscar espacios, use grep:

$ echo "This is a sentence." | grep " " > /dev/null $ echo $? 0 $ echo "Thisisasentence." | grep " " > /dev/null $ echo $? 1