Tratamiento de barras invertidas a través de conchas


9

Cómo hacer echoy printfbarras invertidas en tratar zsh, bashy 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 zshy 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?


3
Uso printf, echono es portátil en el sentido.
jordanm

que la función "foo": sustituir '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)
Olivier Dulac

2
Su función utilizada '$s\n'cuando debería haberlo utilizado '%s\n'.
cjm

Respuestas:


12

zsh echose comporta de la manera estándar, como bashen el modo UNIX. Es decir, se expande \bal carácter ASCII BS como lo requiere la especificación UNIX.

No lo use echopara mostrar cadenas arbitrarias, useprintf :

printf '%s\n' "$1"

print -r -- "$1"También funciona pero es ksh/ zshespecífico.

echo -E - "$1"trabajar con zshy creo que algunos BSD.

cat << EOF
$1
EOF

funciona en cualquier shell similar a Bourne, incluso aquellos de unas pocas décadas cuando no había printfcomando pero generaba un nuevo proceso, y realmente no es necesario hoy en día, ya que ahora lo tenemos en printftodas 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'

foo \\foo\barpasaría la "\foo\bar"cadena a la fooque no se puede reinventar la barra invertida perdida.


Gracias Stephane Por extraño que parezca, la construcción printf '%s\n' "$var"funciona para mí en la línea de comandos ( zsh 5.0.2es decir, la última), pero no dentro de una función (ver mi actualización en el OP). ¿Por qué?
Amelio Vazquez-Reina

1
Es printf '%s\n', no printf '$s\n'quieres. Tenga en cuenta que necesita citar variables en otros shells que no sean zsh( "$1"y no $1) y la sintaxis de definición de función estándar es foo() { ...; }, aunque cualquier shell no lo bashpermita foo() any-command, y function foo { .... }es la kshsintaxis.
Stéphane Chazelas

@ Marcus, esa es una respuesta a una pregunta diferente.
Stéphane Chazelas

1

nueva respuesta: read -r var

-r  raw input - disables interpretion of backslash escapes and line-continuation in the read data

y para mostrar:

printf "%s" "$var"
echo "$var"

Deberia trabajar.

Entonces, para su función foo:

function foo
{
    read -r var
    echo -E "var is : ${var}"
}

$ foo 
\\here\is\some\path
var is : \\here\is\some\path

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 \bsignifica "1 retroceso", o lo que sea.

podría, por ejemplo, usar sed:

sed -e 's,\\,\\\\,g' < the_original > the_escaped_backslaches_version

(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)


Gracias, pero como mencioné en el título: Quiero evitar las barras invertidas.
Amelio Vazquez-Reina

Uy, editaré ^^
Olivier Dulac

¡Gracias! Pero read -r varparece esperar la entrada de STDIN. ¿Qué pasa si lo paso como argumento? (por ejemplo, foo \\here\is\some\path)
Amelio Vazquez-Reina

El shell está interpretando barras invertidas. Es por eso que probablemente debería mover el argumento pasando a una lectura, vea mi ejemplo "foo".
Olivier Dulac

1
iow: desea un manejo "no estándar" de las cadenas por parte del shell: podría hacer que su programa sea más fácil (y más extenso) que cumpla con lo que desea, en lugar de tratar de que el shell invoque ese programa compórtate como quieras. Entonces: pase los argumentos (los que contienen "\" de los que no quiere escapar) una vez que se inicia el programa, a través de "read -r", y no en su línea de comando de invocación de shell.
Olivier Dulac

1

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 echodiscrepancia, es una función incorporada y puede comportarse de manera diferente entre los shells (hasta cierto punto). Por ejemplo, el BASH incorporado tiene una -eopción que le dice que interprete las secuencias de barra invertida, con lo que obtendría el comportamiento que vio en el shell Z.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.