Bash
División de palabras
Buscar..
Sintaxis
- Establezca IFS en nueva línea: IFS = $ '\ n'
- Establecer IFS en cadena nula: IFS =
- Establezca IFS en / carácter: IFS = /
Parámetros
| Parámetro | Detalles |
|---|---|
| IFS | Separador de campo interno |
| -X | Imprimir comandos y sus argumentos a medida que se ejecutan (opción de Shell) |
Observaciones
- La división de palabras no se realiza durante las tareas, por ejemplo,
newvar=$var - La división de palabras no se realiza en la construcción
[[ ... ]] - Use comillas dobles en las variables para evitar la división de palabras
Partiendo con IFS
Para ser más claros, vamos a crear un script llamado showarg :
#!/usr/bin/env bash
printf "%d args:" $#
printf " <%s>" "$@"
echo
Ahora veamos las diferencias:
$ var="This is an example"
$ showarg $var
4 args: <This> <is> <an> <example>
$varse divide en 4 args.IFSson caracteres de espacios en blanco y, por lo tanto, la división de palabras ocurrió en espacios
$ var="This/is/an/example"
$ showarg $var
1 args: <This/is/an/example>
En la división de palabras anterior no se produjo porque no se encontraron los caracteres
IFS.
Ahora vamos a establecer IFS=/
$ IFS=/
$ var="This/is/an/example"
$ showarg $var
4 args: <This> <is> <an> <example>
El
$varse divide en 4 argumentos, no un solo argumento.
¿Qué, cuándo y por qué?
Cuando el shell realiza la expansión de parámetros , la sustitución de comandos , la expansión variable o aritmética , busca límites de palabras en el resultado. Si se encuentra un límite de palabra, el resultado se divide en varias palabras en esa posición. El límite de la palabra se define mediante una variable de shell IFS (Separador de campo interno). El valor predeterminado para IFS es espacio, tabulador y nueva línea, es decir, la división de palabras se producirá en estos tres caracteres de espacio en blanco si no se evita explícitamente.
set -x
var='I am
a
multiline string'
fun() {
echo "-$1-"
echo "*$2*"
echo ".$3."
}
fun $var
En el ejemplo anterior, así es como se ejecuta la función fun :
fun I am a multiline string
$varse divide en 5 argumentos, soloI,amyase imprimirán.
IFS y división de palabras
Vea qué, cuándo y por qué, si no sabe acerca de la afiliación de IFS a la división de palabras
vamos a configurar el IFS en caracteres de espacio solamente:
set -x
var='I am
a
multiline string'
IFS=' '
fun() {
echo "-$1-"
echo "*$2*"
echo ".$3."
}
fun $var
Esta vez la división de palabras solo funcionará en espacios. La función de fun se ejecutará así:
fun I 'am
a
multiline' string
$varse divide en 3 args.I,am\na\nmultilineystringse imprimirán
Vamos a configurar el IFS a nueva línea solamente:
IFS=$'\n'
...
Ahora la fun será ejecutada como:
fun 'I am' a 'multiline string'
$varse divide en 3 args.I am, se imprimiráamultiline string
Veamos qué sucede si establecemos IFS en cadena nula:
IFS=
...
Esta vez la fun se ejecutará así:
fun 'I am
a
multiline string'
$varno se divide, es decir, se mantuvo como un solo argumento.
Puede evitar la división de palabras configurando el IFS en cadena nula
Una forma general de evitar la división de palabras es usar comillas dobles:
fun "$var"
evitará la división de palabras en todos los casos discutidos anteriormente, es decir, la función fun se ejecutará con un solo argumento.
Malos efectos de la división de palabras.
$ a='I am a string with spaces'
$ [ $a = $a ] || echo "didn't match"
bash: [: too many arguments
didn't match
[ $a = $a ]se interpretó como[ I am a string with spaces = I am a string with spaces ].[es el comando detestpara el queI am a string with spacesno es un solo argumento, ¡¡es más bien 6 argumentos !!
$ [ $a = something ] || echo "didn't match"
bash: [: too many arguments
didn't match
[ $a = something ]se interpretó como[ I am a string with spaces = something ]
$ [ $(grep . file) = 'something' ]
bash: [: too many arguments
El comando
grepdevuelve una cadena multilínea con espacios, así que puedes imaginar cuántos argumentos hay ...: D
Vea qué, cuándo y por qué para lo básico.
Utilidad de la división de palabras
Hay algunos casos donde la división de palabras puede ser útil:
Rellenando matriz:
arr=($(grep -o '[0-9]\+' file))
Esto llenará
arrcon todos los valores numéricos encontrados en el archivo
Corriendo a través del espacio palabras separadas:
words='foo bar baz'
for w in $words;do
echo "W: $w"
done
Salida:
W: foo
W: bar
W: baz
Pasando parámetros separados por espacios que no contienen espacios en blanco:
packs='apache2 php php-mbstring php-mysql'
sudo apt-get install $packs
o
packs='
apache2
php
php-mbstring
php-mysql
'
sudo apt-get install $packs
Esto instalará los paquetes. Si cita dos veces los
$packsse producirá un error.
Unquoetd
$packsestá enviando todos los nombres de paquetes separados por espacios como argumentos aapt-get, mientras que si lo cita enviará la cadena de$packscomo un solo argumento y luegoapt-getintentará instalar un paquete llamadoapache2 php php-mbstring php-mysql(para el primero) que obviamente no existe
Vea qué, cuándo y por qué para lo básico.
División por cambios de separador.
Simplemente podemos reemplazar los separadores del espacio a una nueva línea, como se muestra en el siguiente ejemplo.
echo $sentence | tr " " "\n"
Dividirá el valor de la sentence variable y lo mostrará línea por línea respectivamente.