
En un POSIX sh, o en el shell Bourne (como en Solaris 10 /bin/sh
), es posible tener algo como:
a='some var with spaces and a special space'
printf "%s\n" $a
Y, con el valor predeterminado IFS
, obtienes:
some
var
with
spaces
and
a
special space
Es decir, ¿proteger el espacio entre special
y space
mediante alguna combinación de citar o escapar?
El número de palabras a
no se conoce de antemano, o intentaría algo como:
a='some var with spaces and a special\ space'
printf "%s\n" "$a" | while read field1 field2 ...
El contexto eseste errorinformó en Cassandra, donde OP intentó establecer una variable de entorno que especifica opciones para la JVM:
export JVM_EXTRA_OPTS='-XX:OnOutOfMemoryError="echo oh_no"'
En el script que ejecuta Cassandra, que debe admitir POSIX sh y Solaris sh:
JVM_OPTS="$JVM_OPTS $JVM_EXTRA_OPTS"
#...
exec $NUMACTL "$JAVA" $JVM_OPTS $cassandra_parms -cp "$CLASSPATH" $props "$class"
En mi opinión, la única salida aquí es utilizar un script que incluya el echo oh_no
comando. ¿Hay otra manera?
Respuesta1
No precisamente.
Una solución es reservar un carácter como separador de campo. Evidentemente no será posible incluir ese personaje, sea cual sea, en una opción. La tabulación y la nueva línea son candidatos obvios, si el idioma de origen facilita su inserción. Yo evitaría los caracteres multibyte si desea portabilidad (por ejemplo, el guión y BusyBox no admiten caracteres multibyte).
Si confía en la división IFS, no olvide desactivar la expansión con comodines con set -f
.
tab=$(printf '\t')
IFS=$tab
set -f
exec java $JVM_EXTRA_OPTS …
Otro enfoque consiste en introducir una sintaxis de citas. Una sintaxis de cita muy común es que una barra invertida protege el siguiente carácter. La desventaja de utilizar barras invertidas es que hay tantas herramientas diferentes que las utilizan para citar caracteres que a veces puede resultar difícil determinar cuántas barras invertidas necesitas.
set java
eval 'set -- "$@"' $(printf '%s\n' "$JVM_EXTRA_OPTS" | sed -e 's/[^ ]/\\&/g' -e 's/\\\\/\\/g') …
exec "$@"
Respuesta2
Si estuvieras usando Bash o similar, una matriz sería suficiente:
a=(some var with spaces and a 'special space')
Pero como el shell POSIX no los tiene, el mejor enfoque interno que puedo ver es utilizar un espacio especial. El espacio sin separación (U+00A0) es adecuado para este propósito, pero estar fuera de ASCII requiere un acuerdo sobre el juego de caracteres del script.
a="some var with spaces and a special space"
# this is a non-breaking space ------^
echo "$a" \
| while read word; do printf '%s\n' ${word} | sed 's@ @ @g'; done
# this is a non-breaking space ----------------------^
Esto produce:
some
var
with
spaces
and
a
special space
Por el momento, no estoy seguro de cómo incluir esto en una expansión variable (necesitará una subcapa), pero esto debería ofrecer un punto de partida para una mayor investigación.