Perché il comando pipe “l | grep "1" "ottieni il risultato sbagliato?


13

Come mostra la foto, io uso lper ottenere il file nella cartella corrente. E poi voglio ottenere il file con il numero 1, quindi uso il pipee il grep.

Ma perché il file 2e 22mostra? E qual è il 1;34m?

$ l
./ ../ 1 11 2 22
$ l | grep "1"
1;34m./ 1;32m../ 1 11 2 22

Aggiornare

Ho già alias il comando lnel mio zshrcfile.

 alias lsp="ls"
 alias ll='ls -alF'
 alias la='ls -A'
 alias l='ls -CF'
 alias ls="ls -alh --color"

Ed ecco il risultato del typecomando:

>$ type ls
ls is an alias for ls -alh --color

> $ type l
l is an alias for ls -CF

4
Si prega di non pubblicare schermate di testo. Copia qui il testo e applica la formattazione del codice.
muru,

@muru Penso che intendevi chiedere l'output post di type -a l?
WinEunuuchs2Unix il

@ WinEunuuchs2Unix ah, sì.
muru,

@ Ti prego, posso chiederti di pubblicare l'output del type lscomando per favore? hai modificato l' lsalias in qualche modo?
Sergiy Kolodyazhnyy,

@Serg già aggiornato.
Lee,

Risposte:


27

Prima di tutto, quello che stai cercando di fare l| grep <filename>è male. Non farlo Ecco perché.

l il comando è davvero un alias di ls -CF

$ type -a l
l is aliased to `ls -CF'

Di default in Ubuntu bash, lsè un alias di ls --color=auto. Come ha sottolineato steeldriver nei commenti, --color=autosi suppone di disattivare la colorazione. Nel tuo caso specifico, hai alias ls="ls -alh --color"e alias l="ls -CF", che sostanzialmente finisce per essere ls -alh --color -CF. Questa particolare combinazione di interruttori invia ancora output colorato su un tubo. Per esempio:

$ ls -alh --color -CF ~/TESTDIR | cat -A                                                                                 
^[[0m^[[01;34m.^[[0m/  ^[[01;34m..^[[0m/  1.txt  2.txt  3.txt  out.txt$

Notare come le directory .e ..abbiano le stesse sequenze di escape.

Che cosa significa tutto questo

Ciò significa che lverrà visualizzato un elenco di file colorato in base al tipo di file. Il problema è che la colorazione avviene con l'uso di sequenze di escape . Ecco cosa 1:34msono: sono la sequenza di escape per colori specifici.

Il problema principale è che l'analisi lsspesso porta a output errati e disastri negli script, semplicemente perché lsconsente sequenze di escape come spiegato in precedenza e altri caratteri speciali. Vedi questo articolo per maggiori informazioni: http://mywiki.wooledge.org/ParsingLs

Cosa dovresti fare:

Usa il findcomando:

bash-4.3$ ls
1.txt  2.txt  3.txt  out.txt
bash-4.3$ find . -maxdepth 1 -iname "*1*"
./1.txt

Potresti fare qualcosa del genere con shell glob e moderno [[comando di test :

bash-4.3$ for file in * ;do if [[ "$file" =~ "1"  ]] ;then echo "$file" ;fi ; done
1.txt

O forse usa python, che ha capacità di gestione dei nomi dei file molto migliori rispetto al bashsolo

bash-4.3$ python -c 'import os;print [f for f in os.listdir(".") if "1" in f ]'
['1.txt']

Se non è necessario elaborare l'output di ls, anche il semplice globbing lspuò fare il lavoro. (Ricorda, questo è solo per visualizzare l'elenco di file, non per passarlo a un altro programma per gestire il testo di output)

bash-4.3$ ls *1*
1.txt

2
Penso che l'output verrà colorato in una pipe solo se --color=alwaysviene specificato anche - come parte dell'alias per lo in un alias precedente per lssé (sostituendo il valore predefinito alias ls='ls --color=auto').
Steeldriver,

@steeldriver Un buon punto, ma non è quello che è lsdi default in bash? type lsmi dà che è un alias perls --color=auto
Sergiy Kolodyazhnyy il

1
Sì, questo è il valore predefinito, ma autodisattiva il colore in una pipe AFAIK. Per vedere le sequenze di colori ANSI, è necessario che sia stato modificato --color=alwaysin lsalias o lalias
steeldriver,

Oh, capisco cosa intendi. È molto strano.
Sergiy Kolodyazhnyy,

@steeldriver Quindi ho chiesto a OP di pubblicare i suoi alias, e apparentemente quello che hanno, vale a dire ls --color, non impedisce la colorazione (testato anche io). Aggiornato di conseguenza la mia risposta
Sergiy Kolodyazhnyy il

6

I tuoi comandi le lssono impostati come alias.

Quando li esegui, esegui il piping dell'output attraverso grep "1"(utilizzando |) ogni riga dello schermo in cui 1appare viene visualizzata, con il 1colore rosso.

Perché i nomi dei file ., .., 2e 22appaiono sulla stessa linea dello schermo, vengono visualizzati dal greppure ma non appaiono in rosso, che mostra greple partite.

Il :34mè una sequenza di escape per un colore che non dipinge correttamente. Sulla base della tua domanda rivista con l'output di type -a le type -apuò essere riprodotta nel mio sistema. Nota che dovresti cambiare il tuo alias da --colora --color=auto:

Uscita a colori

colore ls


Le 1:34mcose non sono corruzione, sono sequenze di escape utilizzate per la colorazione del testo. Vedi la mia risposta su quella parte;)
Sergiy Kolodyazhnyy il

@Serg Grazie. Ho rivisto in base alla domanda rivista OP con alias.
WinEunuuchs2Unix,

1

Nella tua prova, stavi chiamando il tuo lsalias, quindi il 1;34mrumore e simili che provengono dalla colorazione, e poiché la pipe |riceve tutto questo sulla stessa linea, grepcorrisponde al file 1da quella linea e di conseguenza stampa questa linea. Questo è ciò che vedi sullo schermo.

Quando stai facendo cose del genere, è sempre bene tornare al comando di sistema con 1 risultato per riga.

Per eliminare gli alias basta digitare \lse utilizzare l'opzione -1per stampare i risultati separati da avanzamenti di riga.

$ \ls -1 | grep "1"
1
11

Nota: il metodo barra rovesciata funziona con tutti i comandi, \commandchiama semplicemente il comando di sistema senza precedenti.

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.