in

shell – ¿Cómo divido una cadena en un delimitador en Bash?

apple touch icon@2

Respuesta compatible

Hay muchas formas diferentes de hacer esto en bash.

Sin embargo, es importante tener en cuenta primero que bash tiene muchos especial características (las llamadas bashismos) que no funcionará en ningún otro shell.

En particular, matrices, matrices asociativas, y sustitución de patrones, que se utilizan en las soluciones de esta publicación, así como otras en el hilo, son bashismos y puede que no funcione bajo otros conchas que mucha gente usa.

Por ejemplo: en mi Debian GNU / Linux, hay un estándar shell llamado guión; Conozco a muchas personas a las que les gusta usar otro shell llamado ksh; y también hay una herramienta especial llamada busybox con su propio intérprete de shell (ash).

Cadena solicitada

La cadena que se dividirá en la pregunta anterior es:

IN="[email protected];[email protected]"

Usaré una versión modificada de esta cadena para asegurarme de que mi solución sea robusta para cadenas que contengan espacios en blanco, lo que podría romper otras soluciones:

IN="[email protected];[email protected];Full Name <[email protected]>"

Cadena dividida según el delimitador en bash (versión> = 4.2)

En puro bash, podemos crear un formación con elementos divididos por un valor temporal para IFS (los separador de campo de entrada). El IFS, entre otras cosas, dice bash qué carácter (s) debe tratar como un delimitador entre elementos al definir una matriz:

IN="[email protected];[email protected];Full Name <[email protected]>"

# save original IFS value so we can restore it later
oIFS="$IFS"
IFS=";"
declare -a fields=($IN)
IFS="$oIFS"
unset oIFS

En versiones más recientes de bash, anteponer un comando con una definición de IFS cambia el IFS para ese comando solamente y lo restablece al valor anterior inmediatamente después. Esto significa que podemos hacer lo anterior en una sola línea:

IFS=; read -a fields <<<"$IN"
# after this command, the IFS resets back to its previous value (here, the default):
set | grep ^IFS=
# IFS=$' tn'

Podemos ver que la cuerda IN se ha almacenado en una matriz llamada fields, dividido en punto y coma:

set | grep ^fields=\|^IN=
# fields=([0]="[email protected]" [1]="[email protected]" [2]="Full Name <[email protected]>")
# IN='[email protected];[email protected];Full Name <[email protected]>'

(También podemos mostrar el contenido de estas variables usando declare -p🙂

declare -p IN fields
# declare -- IN="[email protected];[email protected];Full Name <[email protected]>"
# declare -a fields=([0]="[email protected]" [1]="[email protected]" [2]="Full Name <[email protected]>")

Tenga en cuenta que read es el mas rapido manera de hacer la división porque no hay tenedores o recursos externos llamados.

Una vez que se define la matriz, puede utilizar un bucle simple para procesar cada campo (o, más bien, cada elemento de la matriz que ha definido ahora):

# `"${fields[@]}"` expands to return every element of `fields` array as a separate argument
for x in "${fields[@]}" ;do
    echo "> [$x]"
    done
# > [[email protected]]
# > [[email protected]]
# > [Full Name <[email protected]>]

O puede eliminar cada campo de la matriz después de procesar utilizando un cambiando enfoque, que me gusta:

while [ "$fields" ] ;do
    echo "> [$fields]"
    # slice the array 
    fields=("${fields[@]:1}")
    done
# > [[email protected]]
# > [[email protected]]
# > [Full Name <[email protected]>]

Y si solo desea una impresión simple de la matriz, ni siquiera necesita recorrerla:

printf "> [%s]n" "${fields[@]}"
# > [[email protected]]
# > [[email protected]]
# > [Full Name <[email protected]>]

Actualización: bash reciente> = 4.4

En versiones más recientes de bash, también puedes jugar con el comando mapfile:

mapfile -td ; fields < <(printf "%s " "$IN")

¡Esta sintaxis conserva caracteres especiales, nuevas líneas y campos vacíos!

Si no desea incluir campos vacíos, puede hacer lo siguiente:

mapfile -td ; fields <<<"$IN"
fields=("${fields[@]%$'n'}")   # drop 'n' added by '<<<'

Con mapfile, también puede omitir la declaración de una matriz e implícitamente «recorrer» los elementos delimitados, llamando a una función en cada uno:

myPubliMail () {printf "Seq:% 6d: Enviando correo a '% s' ..." $ 1 "$ 2" # mail -s "Esto no es spam ..." "$ 2"  ruta / a / cuerpo printf " e[3D, done.n"
}

mapfile < <(printf "%s " "$IN") -td ; -c 1 -C myPubliMail

(Note: the

Deja una respuesta

Tu dirección de correo electrónico no será publicada.

Función de biblioteca C – piso ()

gfg 200x200 min

Cadena a entero en Java – parseInt ()