Dlaczego polecenie potoku „l | grep ”1” „uzyskać zły wynik?

13

Jak pokazuje zdjęcie, używam, laby pobrać plik do bieżącego folderu. A potem chcę uzyskać plik z numerem 1, więc używam pipei grep.

Ale dlaczego wyświetlają się pliki 2i 22? A co jest 1;34m?

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

Aktualizacja

Mam już alias polecenia lw moim zshrcpliku.

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

A oto wynik typepolecenia:

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

> $ type l
l is an alias for ls -CF
Zawietrzny
źródło
4
Nie publikuj zrzutów ekranu z tekstem. Skopiuj tekst tutaj i zastosuj formatowanie kodu.
muru
@muru Myślę, że chciałeś zapytać o wynik postu type -a l?
WinEunuuchs2Unix
@ WinEunuuchs2Unix ah, tak.
muru
@Lee, czy mogę prosić o przesłanie danych wyjściowych type lspolecenia? czy lsw jakikolwiek sposób zmodyfikowałeś alias?
Sergiy Kolodyazhnyy
@Serg jest już zaktualizowany.
Lee,

Odpowiedzi:

27

Po pierwsze, to, co próbujesz zrobić, l| grep <filename>jest złe. Nie rób tego Dlatego.

l polecenie jest naprawdę pseudonimem ls -CF

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

Domyślnie w Ubuntu bash, lsjest aliasem ls --color=auto. Jak zauważył Steeldriver w komentarzach, --color=automa wyłączać kolorowanie. W twoim konkretnym przypadku masz alias ls="ls -alh --color"i alias l="ls -CF", co w gruncie rzeczy kończy się ls -alh --color -CF. Ta szczególna kombinacja przełączników nadal wysyła kolorowe wyjście przez potok. Na przykład:

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

Zauważ, że katalogi .i ..mają takie same sekwencje specjalne.

Co to wszystko znaczy

Oznacza to, że lwyświetli pokolorowaną listę plików według typu pliku. Problem polega na tym, że koloryzacja zachodzi przy użyciu sekwencji ucieczki . Właśnie takie 1:34msą rzeczy - są sekwencjami ucieczki dla określonych kolorów.

Główny problem polega na tym, że parsowanie lsczęsto prowadzi do złych wyników i katastrof w skryptach, po prostu dlatego, że lsumożliwia sekwencje specjalne, jak wyjaśniono wcześniej, i inne znaki specjalne. Zobacz ten artykuł, aby uzyskać więcej informacji: http://mywiki.wooledge.org/ParsingLs

Co powinieneś robić:

Użyj findpolecenia:

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

Możesz zrobić coś takiego z globem powłoki i nowoczesnym [[poleceniem testowym :

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

A może użyj Pythona, który ma znacznie lepsze możliwości obsługi nazw plików niż bashsam

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

Jeśli nie ma potrzeby przetwarzania wyniku ls, proste globowanie za pomocą lsmoże również wykonać pracę. (Pamiętaj, że służy to tylko do przeglądania listy plików, a nie do przekazywania jej do innego programu w celu obsługi tekstu wyjściowego)

bash-4.3$ ls *1*
1.txt
Sergiy Kolodyazhnyy
źródło
2
Myślę, że dane wyjściowe zostaną pokolorowane w potoku tylko wtedy, gdy --color=alwaysjest to określone - albo jako część aliasu dla siebie, lalbo w poprzednim aliasie ls(zastępując domyślny alias ls='ls --color=auto').
steeldriver
@steeldriver Dobra uwaga, ale czy nie jest to lsdomyślnie domyślna wersja bash? type lsdaje mi do ls --color=auto
zrozumienia
1
Tak, to jest ustawienie domyślne - ale autowyłącza kolor w rurce AFAIK. Aby zobaczyć sekwencje kolorów ANSI, trzeba było zmienić to --color=alwaysna lsalias lub lalias
steeldriver,
Och, rozumiem co masz na myśli. To bardzo dziwne.
Sergiy Kolodyazhnyy
@steeldriver Więc poprosiłem OP o opublikowanie jego aliasów i najwyraźniej to, co one mają, a mianowicie ls --color, nie zapobiega koloryzacji (przetestowałem to również ja). Zaktualizowałem odpowiednio moją odpowiedź
Sergiy Kolodyazhnyy
6

Twoje li lspolecenia są ustawione jako aliasy.

Kiedy je uruchomisz, potokujesz wyjście grep "1"(używając |) każdą linię ekranu, w której się 1pojawia, jest wyświetlana, z 1czerwonym kolorem.

Ponieważ nazwy plików ., .., 2i 22pojawiają się na tej samej linii na ekranie, są one na wyjściu grepjak dobrze, ale nie są wyświetlane w kolorze czerwonym, który pokazuje grepmeczów.

:34mJest sekwencja ucieczki dla koloru, który nie maluje prawidłowo. Na podstawie zmienionego pytania z danymi wyjściowymi type -a li type -amożna je odtworzyć w moim systemie. Pamiętaj, że powinieneś zmienić swój alias z --colorna --color=auto:

Wyjście kolorów

kolor ls

WinEunuuchs2Unix
źródło
Te 1:34mrzeczy nie są korupcja, są sekwencje używane do kolorowania tekstu. Zobacz moją odpowiedź z tej strony;)
Sergiy Kolodyazhnyy
@Erg Dziękuję. Poprawiłem na podstawie skorygowanego pytania PO z aliasami.
WinEunuuchs2Unix
1

W swojej próbie wzywałeś swój lsalias, a więc 1;34mi podobny hałas pochodzący z kolorowania, a ponieważ rura |odbiera to wszystko w tej samej linii, grepdopasowuje plik 1z tej linii i w konsekwencji drukuje tę linię. Oto, co widzisz na ekranie.

Kiedy robisz takie rzeczy, zawsze dobrze jest wrócić do polecenia systemowego z 1 wynikiem w wierszu.

Aby pozbyć się aliasów, po prostu wpisz \lsi użyj opcji, -1aby wydrukować wyniki oddzielone wierszami.

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

Uwaga: metoda odwrotnego ukośnika działa z każdym poleceniem, \commandpo prostu wywołuje niezmienne polecenie systemowe.

pilko
źródło