Warum der Pipe-Befehl “l | grep "1" "das falsche Ergebnis bekommen?

13

Wie das Bild zeigt, benutze ich l, um die Datei in den aktuellen Ordner zu bekommen. Und dann möchte ich die Datei mit der Nummer bekommen 1, also benutze ich die pipeund die grep.

Aber warum zeigen die 2und 22Datei aus? Und was ist das 1;34m?

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

Aktualisieren

Ich habe bereits einen Alias ​​für den Befehl lin meiner zshrcDatei.

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

Und hier ist das Ergebnis des typeBefehls:

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

> $ type l
l is an alias for ls -CF
Lee
quelle
4
Bitte poste keine Screenshots von Texten. Kopieren Sie den Text hierher und wenden Sie die Code-Formatierung an.
muru
@muru Ich denke, du wolltest die Post-Ausgabe von fragen type -a l?
WinEunuuchs2Unix
@ WinEunuuchs2Unix ah ja.
muru
@Lee darf ich Sie bitten, die Ausgabe des type lsBefehls bitte zu posten ? Haben Sie den lsAlias ​​in irgendeiner Weise geändert ?
Sergiy Kolodyazhnyy
@ Serg bereits aktualisiert.
Lee

Antworten:

27

Zuallererst ist das, was du versuchst, l| grep <filename>schlecht. Tu es nicht. Hier ist der Grund.

l Befehl ist wirklich ein Alias ​​für ls -CF

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

Standardmäßig in Ubuntu bash, lsist ein Alias zu ls --color=auto. Wie steeldriver in den Kommentaren hervorhob, --color=autosoll die Einfärbung ausgeschaltet werden. In Ihrem speziellen Fall haben Sie alias ls="ls -alh --color"und alias l="ls -CF", was im Grunde genommen dazu führt, dass ls -alh --color -CF. Diese spezielle Schalterkombination sendet immer noch farbige Ausgaben über eine Pipe. Beispielsweise:

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

Beachten Sie, wie die .und ..Verzeichnisse haben gleiche Escape - Sequenzen.

Was bedeutet das alles?

Dies bedeutet, dass leine farbige Liste der Dateien nach Dateityp ausgegeben wird. Das Problem ist, dass die Einfärbung unter Verwendung von Escape-Sequenzen erfolgt . Das ist, was 1:34mDinge sind - sie sind Fluchtsequenzen für bestimmte Farben.

Das Hauptproblem ist, dass das Parsen lsin Skripten oft zu falschen Ausgaben und zum Absturz von Skripten führt, einfach weil lsEscape-Sequenzen wie oben erläutert und andere Sonderzeichen möglich sind. Weitere Informationen finden Sie in diesem Artikel: http://mywiki.wooledge.org/ParsingLs

Was solltest du tun:

Verwenden findBefehl ein :

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

Sie könnten so etwas mit Shell Glob und modernen Testbefehlen machen [[:

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

Oder verwenden Sie Python, das eine weitaus bessere Dateibehandlung bietet als bashallein

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

Wenn die Ausgabe von nicht verarbeitet werden muss, kann auch das lseinfache Verschieben mit lsdie Arbeit erledigen. (Denken Sie daran, dies ist nur zum Anzeigen einer Liste von Dateien gedacht, nicht zum Weitergeben an ein anderes Programm, um den ausgegebenen Text zu verarbeiten.)

bash-4.3$ ls *1*
1.txt
Sergiy Kolodyazhnyy
quelle
2
Ich denke, die Ausgabe wird nur in einer Pipe eingefärbt , wenn dies --color=alwaysauch angegeben ist - entweder als Teil des Alias ​​für loder in einem vorherigen Alias ​​für sich lsselbst (anstelle des Standardwerts alias ls='ls --color=auto').
Steeldriver
@steeldriver Guter Punkt, aber ist das nicht das, was lsin Bash standardmäßig ist? type lsgibt mir, dass es ein ls --color=auto
Pseudonym
1
Ja, das ist die Standardeinstellung, autodeaktiviert aber die Farbe in einer Pipe AFAIK. Sehen ANSI - Farbsequenzen zu sein, müssen sie geändert wurden --color=always, entweder in dem lsAlias oder lAlias
steeldriver
Oh, ich verstehe, was du meinst. Das ist sehr merkwürdig.
Sergiy Kolodyazhnyy
@steeldriver Also habe ich OP gebeten, seine Aliase zu posten, und anscheinend verhindert das, was sie haben, nämlich ls --colornicht die Einfärbung (das habe ich auch selbst getestet). Meine Antwort wurde entsprechend aktualisiert
Sergiy Kolodyazhnyy
6

Ihre Befehle lund lswerden als Aliase eingerichtet.

Wenn Sie sie ausführen, leiten Sie die Ausgabe durch grep "1"(mit |) jede Bildschirmzeile, in 1der angezeigt wird, mit der 1Farbe Rot.

Da Dateinamen ., .., 2und 22auf der gleichen Bildschirmzeile erscheinen, sie sind ausgegeben durch grepund erscheinen aber nicht in rot , die zeigt , grepStreichhölzer.

Dies :34mist eine Escape-Sequenz für eine Farbe, die nicht richtig gemalt wird. Gestützt auf Ihre überarbeitete Frage mit der Ausgabe von type -a lund type -aes kann in meinem System reproduziert werden. Bitte beachten Sie, dass Sie Ihren Alias ​​von --colorin ändern sollten --color=auto:

Farbausgabe

Farbe ls

WinEunuuchs2Unix
quelle
Die 1:34mDinge sind keine Korruption, sondern Escape-Sequenzen, die zum Einfärben von Text verwendet werden. Siehe meine Antwort auf diesen Teil;)
Sergiy Kolodyazhnyy
@ Serg Danke. Ich habe auf der Grundlage von OP überarbeitete Frage mit Aliasen überarbeitet.
WinEunuuchs2Unix
1

In Ihrem Versuch haben Sie Ihren lsAliasnamen genannt, also das 1;34mund ähnliche Rauschen, das von der Färbung herrührt, und da die Pipe |all dies in derselben Zeile empfängt, grepstimmt das mit der Datei 1aus dieser Zeile überein und druckt folglich diese Zeile. Dies sehen Sie auf dem Bildschirm.

Wenn Sie so etwas tun, ist es immer gut, mit 1 Ergebnis pro Zeile zum Systembefehl zurückzukehren.

Um Aliase zu entfernen, geben Sie einfach ein \lsund verwenden Sie die Option -1, um die Ergebnisse durch Zeilenvorschübe getrennt zu drucken.

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

Hinweis: Die Backslash-Methode funktioniert mit jedem Befehl. Sie \commandruft nur den unaliasierten Systembefehl auf.

pilko
quelle