Dziwne zachowanie „ls -a | grep ^ \. ”

10

Chciałem wyświetlić zawartość pliku pwd i wyświetlić tylko plik zaczynający się od kropki. Próbowałem, ls -a | grep ^\.ale nie mogę zrozumieć, dlaczego dane wyjściowe zawierają również pliki, które nie zaczynają się od kropki. Na przykład:

Pictures
.pip
.pki
.profile
projects
Public

Wiem, że mogę osiągnąć to, co chcę ls -ld .*, jestem ciekawy tego zachowania grepa, którego nie potrafię wyjaśnić.

ps-aux
źródło
Dlaczego nie tylko ls -d .*wymienić wszystkie pliki zaczynające się od .?
Barmar,
Uwaga ostrzegawcza: Nigdy nie podłączaj wyjścia ls do innego polecenia. Zamiast tego użyj find. Ls ma zbyt wiele ideosyncrasies, aby można było zaufać. Zobacz: Pitfall 1 na mywiki.wooledge.org/BashPitfalls - to # 1! Reszta strony też jest świetna.
Joe

Odpowiedzi:

20

Przytoczyć argument grep, tym samymls -a | grep '^\.'

Powodem tego jest to, że powłoka obsługuje \.i zamienia ją z powrotem w zwykły ., który grepnastępnie traktuje jako jednoznaczny znak wieloznaczny. W razie wątpliwości zawsze cytuj ciąg znaków, który zawiera (lub może zawierać) znak specjalny dla powłoki.

roaima
źródło
Dlaczego shell ignoruje \?
ps-aux,
\ jest sekwencją ucieczki, która sprawia, że ​​powłoka traktuje następujący znak jako dosłowny. W tym przypadku grep ^\\.\\ jest traktowane przez powłokę jako pojedynczy odwrotny ukośnik, a ponownie grep traktuje pojedynczy odwrotny ukośnik, a następnie kropkę jako dosłowną kropkę.
Avinash Raj,
11

Musisz umieścić wyrażenie grep w cudzysłowie.

ls -a | grep '^\.'

Uwaga: Nie analizuj danych wyjściowych lspolecenia .

Avinash Raj
źródło
Dlaczego analizowanie wyniku ls jest złe?
ps-aux,
Z linku: W domyślnym trybie, jeśli standardowe wyjście nie jest terminalem, ls oddziela nazwy plików znakami nowej linii. Jest to w porządku, dopóki nie masz pliku z nową linią w nazwie.
Michael Durrant,
@Michael Durrant: Sugeruję, że dopuszczanie nowych linii w nazwach plików jest poważnym błędem systemowym.
jamesqf
@jamesqf - zobacz nowe wiersze w nazwach plików (szczególnie odpowiedź sml ).
don_crissti
0

Jeśli wykonasz cmd ls -a | grep ^ \. wtedy grep nie uważa „\” za znak specjalny i znaczenie „.” nie uciekaj.

Kiedy używamy cmd ls -a | grep „^ \.” następnie grep uważa „\” za znak specjalny i znaczenie „.” ucieka. To da wynik zgodnie z oczekiwaniami.

Jeśli chcesz używać grep cmd bez cudzysłowów, powinieneś również unikać znaku „\”. Możesz oczekiwać wyniku bez podwójnych cudzysłowów, wykonując następujące polecenie. ls -a | grep ^ \\.

Aby uzyskać szczegółowe informacje na temat znaczenia znaków specjalnych w Regex, zapoznaj się z poniższym linkiem. http://www.regular-expressions.info/quickstart.html

AV J
źródło