BASH e comportamento di ritorno al trasporto


11

Ho una domanda veloce.
È normale che bash (sto usando il 4.4.11) non stia visualizzando righe / testo che sono separati / terminano con il semplice \r?

Sono stato un po 'sorpreso di vedere questo comportamento:

$ a=$(printf "hello\ragain\rgeorge\r\n")
$ echo "$a"
george

Ma il testo "ciao di nuovo" è ancora lì, in qualche modo "nascosto":

$ echo "$a" |od -w32 -t x1c
0000000  68  65  6c  6c  6f  0d  61  67  61  69  6e  0d  67  65  6f  72  67  65  0d  0a
          h   e   l   l   o  \r   a   g   a   i   n  \r   g   e   o   r   g   e  \r  \n

E appena giochiamo con bash va bene ... Ma è un potenziale rischio per la sicurezza? Cosa succede se i contenuti della variabile "a" provengono da un mondo esterno e includono "comandi errati" invece che solo ciao?

Un altro test, un po 'incerto questa volta:

$ a=$(printf "ls;\rGeorge\n")
$ echo "$a"
George
$ eval "$a"
0                   awkprof.out       event-tester.log  helloworld.c      oneshot.sh         rightclick-tester.py  tmp                    uinput-simple.py
<directory listing appears with an error message at the end for command George>

Immagina un nascosto rmanziché un nascosto ls.

Stesso comportamento quando si utilizza echo -e:

$ a=$(echo -e "ls;\rGeorge\r\n"); echo "$a"
George

Sono io che faccio qualcosa di sbagliato ...?

Risposte:


20

Le tue echo "$a"stampe "ciao", quindi torna all'inizio della riga (che è ciò che \rfa), stampa "di nuovo", torna indietro, stampa "george", torna indietro e passa alla riga successiva ( \n). È tutto perfettamente normale, ma come sottolinea Chepner , non ha nulla a che fare con Bash: \re \nsono interpretati dal terminale, non da Bash (motivo per cui ottieni l'output completo quando installi il comando od).

Puoi vederlo meglio con

$ a=$(printf "hellooooo\r  again,\rgeorge\r\n")
$ echo "$a"

poiché ciò lascerà la fine del testo sovrascritto:

georgen,o

Non puoi davvero usarlo per nascondere i comandi, solo il loro output (e solo se puoi essere sicuro di sovrascrivere con abbastanza caratteri), a meno evalche tu non lo usi come mostrato (ma evalgeneralmente non è raccomandato). Un trucco più pericoloso è usare i CSS per mascherare i comandi che devono essere copiati e incollati dai siti web.


Abbastanza chiaro, grazie. Sono stato fortunato / sfortunato a usare un'ultima parola nel mio test in grado di sovrascrivere completamente le due parole precedenti.
George Vasiliou,

2
Nota che questo non ha nulla a che fare con bash, comunque; dipende interamente dal terminale come "visualizzare" il ritorno a capo o come visualizzare i caratteri sovrascritti. Ad esempio, sarebbe perfettamente valido per un terminale visualizzare -\r|come qualcosa che assomiglia a un segno più, piuttosto che solo una pipe.
Chepner,

@chepner Buono a sapersi! Grazie per la condivisione. Ho pensato che fosse solo un comportamento bash.
George Vasiliou,

@GeorgeVasiliou No, bashscrive solo byte in un file; sta a chi legge quei byte per interpretarli.
Chepner,

Nitpick: printf, che è un colpo comando incorporato (anche se esiste anche come un eseguibile standalone), interpreta il \r(una sequenza di due byte: 0x5ced 0x72e produce il ritorno (un singolo byte: 0x0d.) Quindi, sì, il terminale interpreta il byte 0x0din modo speciale, ma non interpreta la stringa originale \r.
Suzanne Dupéron,

6

Nel mondo Unix, un ritorno a capo (comunemente codificato come \rnei linguaggi di programmazione) è un carattere di controllo insignificante. Puoi avere ritorni a capo all'interno di una riga di testo, come qualsiasi altro carattere oltre a un avanzamento riga (chiamato anche newline ), che segna la fine di una riga.

In particolare, in uno script bash, un ritorno a capo è un normale carattere costituente parola, come lettere e cifre. Qualsiasi effetto speciale del ritorno del carrello viene dal terminale, non dal guscio.

Un ritorno a capo è un carattere di controllo . Quando lo si stampa su un terminale, invece di visualizzare un glifo , il terminale esegue alcuni effetti speciali. Per un ritorno a capo, l'effetto speciale è spostare il cursore all'inizio della riga corrente. Pertanto, se si stampa una riga che contiene un ritorno a capo nel mezzo, l'effetto è che la seconda metà viene scritta sulla prima metà.

Numerosi altri personaggi di controllo hanno effetti speciali: il carattere backspace sposta il cursore a sinistra di una posizione. Il carattere della campana fa emettere un suono al terminale o attira in altro modo l'attenzione dell'utente. Il personaggio di escape avvia una sequenza di escape che può avere tutti i tipi di effetti speciali.

Se si visualizza un output non attendibile, è necessario cancellare o sfuggire ai caratteri di controllo. Non solo ritorni a capo, ma anche molti altri, in particolare il carattere di fuga, che può causare tutti i tipi di effetti negativi. Vedere "Il cat-ing" di un file può essere un potenziale rischio per la sicurezza? e come evitare attacchi di sequenza di escape nei terminali? per ulteriori informazioni sull'argomento.


0

È possibile visualizzare i ritorni a capo in una variabile bash utilizzando la printffunzione con un %qformato.

$ TESTVAR="$(printf ' Version: 1 \r Build: 20180712 \r Test: 1324')"

$ printf %q $TESTVAR
Version:1$'\r'Build:20180712$'\r'Test:1324

Fonti e ulteriori letture:

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.