Así te sugiero que lo hagas, y te explicaré por qué, pero primero quiero hablar de otra cosa ...
set -- 'Arg 1: Line 1.' \
'Arg 2: Line 2.' \
'and so on for' \
'as long as you might like.'
var="$*"
Muchas de las otras soluciones ofrecidas aquí parecen sugerir que de alguna manera puede afectar el contenido de una variable de shell al alterar sus métodos de expansión. Les puedo asegurar que este no es el caso.
string="some stuff here \
some more stuff here."
echo $string ${#string}
echo "$string" "${#string}"
SALIDA
some stuff here some more stuff here. 53
some stuff here some more stuff here. 53
Lo que ve arriba es primero una expansión dividida en campo, luego un informe sobre el conteo de bytes para la variable fuente de la expansión, luego una expansión delimitada por comillas y el mismo conteo de bytes. Si bien la salida puede diferir, el contenido de la variable de shell $string
nunca cambia en absoluto, excepto en la asignación.
Lo que es más, si no comprende por qué esto es así, seguramente encontrará sorpresas muy desagradables más temprano que tarde. Intentemos eso de nuevo, pero en condiciones ligeramente diferentes.
IFS=sf
echo $string ${#string}
echo "$string" "${#string}"
Mismo $string
- ambiente diferente.
SALIDA
ome tu here ome more tu here. 53
some stuff here some more stuff here. 53
La división de campos se produce en función de los delimitadores de campo definidos en $IFS
. Hay dos tipos de delimitadores: $IFS
espacios en blanco y $IFS
cualquier otra cosa. Por defecto $IFS
se le asigna la nueva línea de la pestaña de espacio de valores , que son los tres posibles $IFS
valores de espacio en blanco. Sin embargo, se puede cambiar fácilmente, como puede ver arriba, y puede tener efectos drásticos en las expansiones divididas en campos.
$IFS
los espacios en blanco se eluirán por secuencia a un solo campo, y es por eso que echo
una expansión que contenga cualquier secuencia de espacios cuando $IFS
contenga un espacio se evaluará a un solo espacio, porque echo
concatena sus argumentos en los espacios. Pero cualquier valor que no sea un espacio en blanco no se eliminará de la misma manera, y cada delimitador que aparece siempre obtiene un campo en sí mismo, como se puede ver en la expansión de cosas anterior.
Esto no es lo peor de todo. Considera este otro $string
.
IFS=$space$tab$newline
cd emptydir
string=" * * * \
* * * "
echo $string ${#string}
echo "$string" "${#string}"
SALIDA
* * * * * * 30
* * * * * * 30
Se ve bien, ¿verdad? Bueno, alteremos el medio ambiente nuevamente.
touch file1 file2 file3 file4 file5
echo $string ${#string}
echo "$string" "${#string}"
SALIDA
file1 file2 file3 file4 file5 file1 file2 file3 file4 file5 file1 file2 file3 file4 file5 file1 file2 file3 file4 file5 file1 file2 file3 file4 file5 file1 file2 file3 file4 file5 30
* * * * * * 30
Woah
Por defecto, el shell expandirá los globos de nombre de archivo si puede coincidir con ellos. Esto ocurre después de la expansión de parámetros y la división de campos en su orden de análisis y, por lo tanto, cualquier cadena sin comillas es vulnerable de esta manera. Puede desactivar este comportamiento set -f
si lo desea, pero cualquier shell compatible con POSIX siempre se bloqueará de forma predeterminada.
Este es el tipo de cosas con las que te enfrentas cuando sueltas citas en expansiones para satisfacer tus preferencias de sangría. Y aun así, en todos los casos, independientemente de su comportamiento de expansión, el valor real de $string
siempre es el que fue la última vez que lo asignó. Así que volvamos a lo primero.
set -- 'Arg 1: Line 1.' \
'Arg 2: Line 2.' \
'and so on for' \
'as long as you might like.'
var="$*"
echo "$var" "${#var}"
SALIDA
Arg 1: Line 1. Arg 2: Line 2. and so on for as long as you might like. 70
Creo que esta es una forma mucho más sensata de adaptar la sintaxis de shell a sus preferencias de sangría. Lo que estoy haciendo arriba es asignar cada cadena individual a un parámetro posicional, al que se puede hacer referencia por número como $1
o ${33}
, y luego asignar sus valores concatenados para $var
usar el parámetro de shell especial $*
.
Este enfoque no es inmune $IFS
, aun así. Aún así, considero su relación con $IFS
un beneficio adicional a este respecto. Considerar:
IFS=\ ;space_split="$*"
IFS=/; slash_split="$*";IFS='
';new_line_split="$*"
echo "$space_split"
echo "$slash_split"
echo "$new_line_split"
SALIDA
Arg 1: Line 1. Arg 2: Line 2. and so on for as long as you might like.
Arg 1: Line 1./Arg 2: Line 2./and so on for/as long as you might like.
Arg 1: Line 1.
Arg 2: Line 2.
and so on for
as long as you might like.
Como puede ver, $*
concatena cada arg en "$@"
el primer byte en $IFS
. Por lo tanto, guardar su valor mientras $IFS
está asignado de manera diferente obtiene delimitadores de campo diferentes para cada valor guardado. Lo que ves arriba es el valor literal de cada variable, por cierto. Si no quisieras delimitador, harías lo siguiente:
IFS=;delimitless="$*"
echo "$delimitless" "${#delimitless}"
SALIDA
Arg 1: Line 1.Arg 2: Line 2.and so on foras long as you might like. 67