Cómo hacer echo
y printf
barras invertidas en tratar zsh
, bash
y otros proyectiles?
Bajo zsh obtengo el siguiente comportamiento:
$ echo "foo\bar\baz"
foaaz
$ echo "foo\\bar\\baz"
foaaz
$ echo 'foo\bar\baz'
foaaz
$ echo 'foo\\bar\\baz'
foo\bar\baz
Bajo bash , las cosas parecen un poco más consistentes:
bash$ echo "foo\bar\baz"
foo\bar\baz
bash$ echo 'foo\bar\baz'
foo\bar\baz
bash$
Pero más concretamente: ¿Cómo puedo pasar una cadena que contenga barras invertidas como\\foo\bar\something
:
echo
printf
print
y obtener exactamente la misma cadena? (en zsh
y bash
)?
Aquí hay otro experimento con funciones en zsh:
function foo
{
echo -E '$1'
}
$ foo \\here\is\some\path
$1
¿Cómo puedo hacer que solo imprima \\here\is\some\path
?
Actualización (Nota: esto ahora ha sido respondido en el comentario de Stephane)
He intentado lo siguiente en zsh 5.0.2:
function foo
{
printf '$s\n' $1
}
foo '\\some\path'
Pero esto imprime $s
?
printf
,echo
no es portátil en el sentido.'
con"
, e invocar con: foo '\\ aquí \ es \ alguna \ ruta' (de lo contrario la cáscara invocación tiene la oportunidad de interpretar el '\' antes de que lleguen a la función)'$s\n'
cuando debería haberlo utilizado'%s\n'
.Respuestas:
zsh
echo
se comporta de la manera estándar, comobash
en el modo UNIX. Es decir, se expande\b
al carácter ASCII BS como lo requiere la especificación UNIX.No lo use
echo
para mostrar cadenas arbitrarias, useprintf
:print -r -- "$1"
También funciona pero esksh
/zsh
específico.echo -E - "$1"
trabajar conzsh
y creo que algunos BSD.funciona en cualquier shell similar a Bourne, incluso aquellos de unas pocas décadas cuando no había
printf
comando pero generaba un nuevo proceso, y realmente no es necesario hoy en día, ya que ahora lo tenemos enprintf
todas partes.Y, por cierto, debe escapar de las barras diagonales inversas en una línea de comando del shell, ya que es especial para el shell (cada shell pero
rc
), por lo tanto:foo \\foo\bar
pasaría la"\foo\bar"
cadena a lafoo
que no se puede reinventar la barra invertida perdida.fuente
printf '%s\n' "$var"
funciona para mí en la línea de comandos (zsh 5.0.2
es decir, la última), pero no dentro de una función (ver mi actualización en el OP). ¿Por qué?printf '%s\n'
, noprintf '$s\n'
quieres. Tenga en cuenta que necesita citar variables en otros shells que no seanzsh
("$1"
y no$1
) y la sintaxis de definición de función estándar esfoo() { ...; }
, aunque cualquier shell no lobash
permitafoo() any-command
, yfunction foo { .... }
es laksh
sintaxis.nueva respuesta: read -r var
y para mostrar:
Deberia trabajar.
Entonces, para su función foo:
respuesta anterior a continuación (no responde, pero tal vez sea útil ^^)
basta con sustituir cada uno
\
por\\
decirle a la concha "que una literall\
quiero". de lo contrario (por ejemplo, en zsh, en su ejemplo) podría ser que\b
significa "1 retroceso", o lo que sea.podría, por ejemplo, usar sed:
(vea cómo también necesita escapar "\" allí, para decirle a sed lo mismo: "es un literall" \ "Quiero) (y observe que lo rodeo por '' y no" "para evitar que el intérprete interprete la mayor parte también)
fuente
read -r var
parece esperar la entrada deSTDIN
. ¿Qué pasa si lo paso como argumento? (por ejemplo, foo\\here\is\some\path
)En términos generales, no puede, porque la barra diagonal inversa es el carácter de escape (y como tal tiene que escapar cuando se requiere su valor literal). BASH proporciona comillas simples para este propósito, sin embargo, no puede usar escapar una comilla simple dentro de una cadena entre comillas simples.
En cuanto a la
echo
discrepancia, es una función incorporada y puede comportarse de manera diferente entre los shells (hasta cierto punto). Por ejemplo, el BASH incorporado tiene una-e
opción que le dice que interprete las secuencias de barra invertida, con lo que obtendría el comportamiento que vio en el shell Z.fuente