it-swarm.com.de

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

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 1 erhalten, also verwende ich die pipe und die grep.

Aber warum werden die Dateien 2 und 22 angezeigt? Und was ist der 1;34m?

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

pdate

Ich habe bereits den Befehl l in meiner zshrc -Datei alias.

 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 Befehls type:

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

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

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'

In Ubuntus bash ist ls standardmäßig ein Alias ​​für ls --color=auto. Wie SteelRiver in den Kommentaren hervorhob, soll --color=auto die Einfärbung ausschalten. In Ihrem speziellen Fall haben Sie alias ls="ls -alh --color" und alias l="ls -CF", was im Grunde genommen zu ls -alh --color -CF führt. Diese spezielle Schalterkombination sendet immer noch farbige Ausgaben über eine Pipe. Zum Beispiel:

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

Beachten Sie, dass die Verzeichnisse . und .. dieselben Escape-Sequenzen haben.

Was bedeutet das alles?

Dies bedeutet, dass l eine farbige Liste von Dateien nach Dateityp ausgibt. Das Problem ist, dass die Einfärbung mit Escape-Sequenzen erfolgt. Das ist, was 1:34m Dinge sind - sie sind Escape-Sequenzen für bestimmte Farben.

Das Hauptproblem ist, dass das Parsen von ls häufig zu einer falschen Ausgabe und zu Katastrophen in Skripten führt, einfach weil ls Escape-Sequenzen wie oben erläutert und andere Sonderzeichen zulässt. Weitere Informationen finden Sie in diesem Artikel: http://mywiki.wooledge.org/ParsingLs

Was solltest du tun:

Verwenden Sie den Befehl find:

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 dem modernen Befehl test [[ tun:

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

Oder verwenden Sie Python, das weitaus bessere Möglichkeiten zur Verarbeitung von Dateinamen bietet als bash alleine

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

Wenn die Ausgabe von ls nicht verarbeitet werden muss, kann auch das einfache Verschieben mit ls die 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
27

Ihre Befehle l und ls werden als Aliase eingerichtet.

Wenn Sie die Ausgabe durch grep "1" leiten (mit |), wird jede Bildschirmzeile, in der 1 angezeigt wird, mit dem 1 in roter Farbe angezeigt.

Da die Dateinamen ., .., 2 und 22 in derselben Bildschirmzeile erscheinen, werden sie von grep ebenfalls ausgegeben, jedoch nicht in roter Schrift angezeigt was grep Übereinstimmungen zeigt.

Der :34m ist eine Escape-Sequenz für eine Farbe, die nicht richtig gemalt wird. Basierend auf Ihrer überarbeiteten Frage mit der Ausgabe von type -a l und type -a kann es in meinem System reproduziert werden. Bitte beachten Sie, dass Sie Ihren Alias ​​von --color in --color=auto ändern sollten:

Farbausgabe

color ls

6

In Ihrer Studie haben Sie Ihren ls -Aliasnamen genannt, also das 1;34m und ähnliche Rauschen, die beim Färben auftreten, und da die Pipe | dies alles auf derselben Leitung empfängt, erhält die grep stimmt mit der Datei 1 aus dieser Zeile überein und druckt diese Zeile folglich aus. 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 \ls ein und verwenden Sie die Option -1, um die Ergebnisse durch Zeilenvorschübe getrennt auszudrucken.

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

Hinweis: Die Backslash-Methode funktioniert mit jedem Befehl. \command ruft nur den Systembefehl ohne Alias ​​auf.

1
pilko