Trattamento di barre inverse tra le conchiglie


9

Come fare echoe printfbackslash trattare in zsh, bashe altre shell?

Sotto zsh ottengo il seguente comportamento:

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

Sotto bash , le cose sembrano un po 'più coerenti:

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

Ma più concretamente: come posso passare una stringa contenente barre rovesciate come\\foo\bar\something :

  • echo
  • printf
  • print

e ottieni esattamente la stessa stringa? (in zshe bash)?

Ecco un altro esperimento con funzioni in zsh:

function foo
{
    echo -E '$1'
}

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

Come posso averlo appena stampato \\here\is\some\path?

Aggiornamento (Nota: questo è stato risposto nel commento di Stephane)

Ho provato quanto segue in zsh 5.0.2:

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

foo '\\some\path'

Ma questo stampa $s?


3
Usa printf, echonon è portatile al riguardo.
Giordania,

tu funzione "pippo": sostituiscilo 'con "e invocalo con: pippo '\\ here \ is \ some \ path' (altrimenti la shell che invoca ha la possibilità di interpretare il '\' prima che arrivino alla funzione)
Olivier Dulac

2
La tua funzione utilizzata '$s\n'quando avrebbe dovuto essere utilizzata '%s\n'.
cjm

Risposte:


12

zsh echosi comporta in modo standard, come bashnella modalità UNIX. Cioè si espande \bal carattere ASCII BS come richiede la specifica UNIX.

Non utilizzare echoper visualizzare stringhe arbitrarie, utilizzareprintf :

printf '%s\n' "$1"

print -r -- "$1"funziona anche ma è ksh/ zshspecifico.

echo -E - "$1"lavorare con zshe credo alcuni BSD.

cat << EOF
$1
EOF

funziona in qualsiasi shell tipo Bourne, anche quelle di qualche decennio in cui non vi era alcun printfcomando ma generava un nuovo processo e non è realmente necessario al giorno d'oggi come oggi abbiamo printfovunque.

E a proposito, è necessario sfuggire alle barre rovesciate su una riga di comando della shell in quanto è speciale per la shell (ma tutte le shell rc), quindi:

$ foo '\\foo\bar'

foo \\foo\barpasserebbe la "\foo\bar"stringa a foocui non è possibile reinventare la barra rovesciata persa.


Grazie Stephane. Stranamente, la costruzione printf '%s\n' "$var"funziona per me sulla riga di comando ( zsh 5.0.2, cioè l'ultima), ma non all'interno di una funzione (vedere il mio aggiornamento nell'OP). Perché?
Amelio Vazquez-Reina

1
È printf '%s\n', non printf '$s\n'vuoi. Si noti che è necessario citare le variabili in shell diverse da zsh( "$1", non $1) e la sintassi della definizione della funzione standard è foo() { ...; }, sebbene qualsiasi shell ma bashpermetta foo() any-command, ed function foo { .... }è la kshsintassi.
Stéphane Chazelas,

@Marcus, questa è una risposta a una domanda diversa.
Stéphane Chazelas,

1

nuova risposta: leggi -r var

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

e per visualizzare:

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

dovrebbe funzionare.

Quindi per la tua funzione foo:

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

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

vecchia risposta di seguito (non risponde, ma forse utile ^^)

basta sostituire ogni \dal \\dire al guscio "che un literall \che voglio". altrimenti (ad esempio in zsh, nel tuo esempio) potrebbe essere che \bsignifica "1 backspace", o qualsiasi altra cosa.

potresti ad esempio usare sed:

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

(vedi come devi anche scappare "\" lì, per dire a sed la stessa cosa: "è un letterale" \ "Voglio) (e nota che lo circondo di '' e non" "per evitare che la shell interpreti anche la maggior parte)


Grazie ma come ho già detto nel titolo: voglio evitare di sfuggire alle barre rovesciate.
Amelio Vazquez-Reina,

oops, lo modificherò ^^
Olivier Dulac il

Grazie! Ma read -r varsembra attendere input da STDIN. E se lo sto passando come argomento? (es. foo \\here\is\some\path)
Amelio Vazquez-Reina

la shell sta interpretando le barre rovesciate. Ecco perché probabilmente dovresti spostare l'argomento passando a una lettura, vedi il mio esempio "pippo".
Olivier Dulac,

1
iow: vuoi una gestione "non standard" delle stringhe da parte della shell: potresti più facilmente (e più ampiamente) far sì che il tuo programma sia conforme a quello che vuoi, invece di provare a fare in modo che il programma invocazione shell comportati come vuoi tu. Quindi: passa gli args (quelli che contengono "\" di cui non vuoi scappare) una volta avviato il programma, tramite "read -r", e non sulla riga di comando della shell che invoca.
Olivier Dulac,

1

In generale non puoi, perché la barra rovesciata è il carattere di escape (e come tale deve essere evitato quando è richiesto il suo valore letterale). BASH fornisce virgolette singole per questo scopo, tuttavia non è possibile usare escape tra virgolette singole all'interno di una stringa tra virgolette singole.

Per quanto riguarda la echodiscrepanza, è integrato e può comportarsi in modo diverso tra le shell (in una certa misura). Ad esempio il BASH integrato ha -eun'opzione che gli dice di interpretare le sequenze di barra rovesciata - con esso otterresti il ​​comportamento che hai visto nella shell Z.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.