Tratamento de barras invertidas em conchas

9

Como fazer echoe printfbarras invertidas tratamento em zsh, bashe outras conchas?

No zsh , recebo o seguinte comportamento:

$ echo "foo\bar\baz"
foaaz
$ echo "foo\\bar\\baz"
foaaz
$ echo 'foo\bar\baz'
foaaz
$ echo 'foo\\bar\\baz'
foo\bar\baz

Sob o bash , as coisas parecem um pouco mais consistentes:

bash$ echo "foo\bar\baz"
foo\bar\baz
bash$ echo 'foo\bar\baz'
foo\bar\baz
bash$

Mas, mais concretamente: como passar uma string contendo barras invertidas, como\\foo\bar\something :

  • echo
  • printf
  • print

e obter exatamente a mesma string? (em zshe bash)?

Aqui está outro experimento com funções no zsh:

function foo
{
    echo -E '$1'
}

$ foo \\here\is\some\path
$1

Como posso imprimir apenas \\here\is\some\path?

Atualização (Nota: isso já foi respondido no comentário de Stephane)

Eu tentei o seguinte no zsh 5.0.2:

function foo
{
    printf '$s\n' $1 
}

foo '\\some\path'

Mas isso imprime $s?

Amelio Vazquez-Reina
fonte
3
Use printf, echonão é portátil no que diz respeito.
Jordanm 28/03
a função "foo": substitua 'por "e chame-a por: foo '\\ here \ is \ some \ path' (caso contrário, o shell de chamada terá a chance de interpretar o '\' antes de chegar à função)
Olivier Dulac
2
Sua função usada '$s\n'quando deveria ter sido usada '%s\n'.
Cjm 29/03/2013

Respostas:

12

zsh echose comporta da maneira padrão, como bashno modo UNIX. Ou seja, ele se expande \bpara o caractere ASCII BS conforme a especificação do UNIX exige.

Não use echopara exibir seqüências arbitrárias, useprintf :

printf '%s\n' "$1"

print -r -- "$1"também funciona, mas é ksh/ zshespecífico.

echo -E - "$1"trabalhar com zshe acredito que alguns BSDs.

cat << EOF
$1
EOF

funciona em qualquer shell tipo Bourne, mesmo em algumas décadas em que não havia printfcomando, mas gerou um novo processo, e realmente não é necessário hoje em dia, como temos em printftoda parte.

E, a propósito, você precisa escapar de barras invertidas em uma linha de comando do shell, pois é especial para o shell (todos os shell, exceto rc), então:

$ foo '\\foo\bar'

foo \\foo\barpassaria a "\foo\bar"string para a fooqual não é possível reinventar a barra invertida perdida.

Stéphane Chazelas
fonte
Obrigado, Stephane. Curiosamente, a construção printf '%s\n' "$var"funciona para mim na linha de comando ( zsh 5.0.2ou seja, a mais recente), mas não dentro de uma função (veja minha atualização no OP). Por quê?
Amelio Vazquez-Reina
1
Não é printf '%s\n'isso que printf '$s\n'você quer. Observe que você precisa citar variáveis ​​em outros shells que não sejam zsh( "$1", not $1) e a sintaxe de definição de função padrão é foo() { ...; }, embora qualquer shell bashpermita foo() any-command, e function foo { .... }é a kshsintaxe.
Stéphane Chazelas
@ Marcus, essa é uma resposta para uma pergunta diferente.
Stéphane Chazelas 29/04/19
1

nova resposta: read -r var

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

e para exibir:

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

Deveria trabalhar.

Então, para a sua função foo:

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

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

resposta antiga abaixo (sem responder, mas talvez útil ^^)

apenas substitua cada um \por \\dizer ao shell "que é um literall que \eu quero". caso contrário (por exemplo, no zsh, no seu exemplo), pode ser que isso \bsignifique "1 backspace" ou qualquer outra coisa.

você poderia, por exemplo, usar sed:

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

(veja como você também precisa escapar "\", para dizer a mesma coisa: "é literalmente" \ "eu quero) (e observe que eu o envolvo com '' e não" "para evitar que o shell interprete a maioria também)

Olivier Dulac
fonte
Obrigado, mas como mencionei no título: quero evitar as barras invertidas.
Amelio Vazquez-Reina
oops, eu vou editar ^^
Olivier Dulac 28/03
Obrigado! Mas read -r varparece esperar pela entrada de STDIN. E se eu estiver passando isso como argumento? (por exemplo, foo \\here\is\some\path)
Amelio Vazquez-Reina
o shell está interpretando barras invertidas. É por isso que você provavelmente deve mover o argumento passando para uma leitura, veja meu exemplo "foo".
Olivier Dulac 28/03
1
iow: você deseja um manuseio "não-padrão" de strings pelo shell: você pode mais facilmente (e mais extensivamente) ter seu programa compatível com o que deseja, em vez de tentar ter o programa de invocação de shell para se comporte como você deseja. Então: passe os argumentos (aqueles que contêm "\" dos quais você não deseja escapar) depois que o programa for iniciado, via "read -r", e não na linha de comando do shell.
Olivier Dulac 29/03
1

De um modo geral, você não pode, porque a barra invertida é o caractere de escape (e, como tal, deve ser escapado quando seu valor literal for necessário). O BASH fornece aspas simples para esse fim, no entanto, você não pode usar uma aspas simples para escapar dentro de uma string entre aspas simples.

Quanto à echodiscrepância, é um componente interno que pode se comportar de maneira diferente entre as conchas (até certo ponto). Por exemplo, o BASH interno tem uma -eopção que o instrui a interpretar seqüências de barra invertida - com isso você obtém o comportamento que viu no shell Z.

peterph
fonte