2009-07-14 10 views
5

Mam dzisiaj dziwną linię kodu, która mówi mi "puste" lub "nie puste" w zależności od tego, czy CWD ma w sobie jakiekolwiek elementy (inne niż . i ..).Jak działa ta linijka Perla, aby sprawdzić, czy katalog jest pusty?

Chcę wiedzieć, jak to działa, ponieważ nie ma dla mnie sensu.

perl -le 'print+(q=not =)[2==(()=<.* *>)].empty' 

Bit Jestem zainteresowany jest <.* *>. Nie rozumiem, jak otrzymuje nazwy wszystkich plików w katalogu.

+0

Zapraszam do edycji tagów dla czegoś bardziej odpowiedniego – dsm

+3

Haha, jesteś taki zabawny! Tarzam się po podłodze śmiejąc się. Zadzwoniłeś do linii perlowej! HAHAHAHAHAHAHAHAHAHAHAHAA! – jrockway

+0

Dobre zgłoszenie do "zaciemnienia roku". Lubię Perla, ale bardziej lubię komentarze w kodzie Perla. – Boldewyn

Odpowiedz

16

To golfowy jednolinijkowy. Flaga -e oznacza wykonanie reszty linii poleceń jako programu. -l umożliwia automatyczne przetwarzanie końca linii.

Część <.* *> to glob zawierający dwa wzory do rozwinięcia: .* i *.

Ta część

(q=not =) 

jest lista zawierająca jedną wartość - łańcuch "nie". q=...= to alternatywny ogranicznik łańcucha, najwyraźniej używany, ponieważ pojedynczy cytat jest używany do zacytowania jednolinijki.

Część [...] jest indeksem dolnym do tej listy. Wartość indeksu będzie albo 0 (wartość „nie  ”) lub 1 (nic, co drukuje jako ciąg pusty), w zależności od wyniku tego porównania:

2 == (()=<.* *>) 

Dużo się tu dzieje. Porównanie sprawdza, czy glob zwrócił listę dokładnie dwóch elementów (z założeniem . i ..), ale jak to jest trudne. Wewnętrzne nawiasy oznaczają pustą listę. Przypisanie do tej listy powoduje umieszczenie kontekstu listy globu w taki sposób, aby zwracała wszystkie pliki w katalogu. (W kontekście skalarnym zachowywałby się jak iterator i zwracałby tylko po jednym naraz.) Sam przypisanie jest oceniane w kontekście skalarnym (znajdującym się po prawej stronie porównania), a zatem zwraca liczbę przypisanych elementów.

Wiodącym + jest uniemożliwienie Perlowi analizowania listy jako argumentów dla print.Końcowy .empty łączy ciąg "pusty" z tym, co wyszło z listy (tj. "Nie  " lub pusty ciąg znaków).

+1

+1 miłe, zwięzłe wyjaśnienie – hillu

+0

To trochę zwodnicze. Funkcja inner() sprawia, że ​​jest to przypisanie do listy, które podaje jego prawy kontekst listy argumentów, ale równie dobrze może być (2 == (@ a = <.* *>)). – ysth

+0

@ysth: Nie jestem pewien, dlaczego uważasz, że to wprowadza w błąd. Ponieważ nie ma nic w wewnętrznej '()' lista jest odrzucana. Celem nawiasów (z punktu widzenia programisty) było narzucenie kontekstu listy na glob. Mógłby zamiast tego przydzielić tablicę (co byłoby wyraźniejszym IMHO), ale nie zrobił tego. Czy odnosisz się do faktu, że puste przypisanie zmienia semantykę z "lista w kontekście skalarnym zwraca ostatni element" do "lista przypisania zwraca liczbę elementów"? Prawdopodobnie powinienem edytować odpowiedź, aby wyjaśnić ten fragment ... –

3

<.* *> oznacza (glob(".*"), glob("*")). glob rozwija wzorce plików w taki sam sposób, jak robi to skorupa.

7
<.* *> 

jest glob składający się z dwóch wzorów: .* są wszystkie nazwy plików rozpoczynające się . i * spełnia wszystkie pliki (to jest inny niż zwykłe konwencji DOS/Windows).

(()=<.* *>) 

oblicza glob w kontekście listy, zwracając wszystkie pasujące nazwy plików.

Następnie porównanie z 2 umieszcza je w kontekście skalarnym, aby porównać 2 z liczbą zwróconych plików. Jeśli numer ten to 2, jedynymi wpisami do katalogu są: . i .., kropka. ;-)

0

Dokumentacja dla tej funkcji to here. (Przewijanie pod koniec odcinka)

+2

Jaką funkcję? Czy to ma być komentarz do czyjejś odpowiedzi? – Telemachus

+0

@Telemachus: <> na myśl glob, przypuszczalnie. – ysth

+0

@Telemachus: Dokumentacja dla glob/<>, jak @ysth wymienione – dsm

2

Uważam, że moduł B::Deparse pomaga trochę w rozszyfrowaniu pewne rzeczy, które rzuca się w oczy większość programistów, takich jak q=...= konstruktem:

$ perl -MO=Deparse,-p,-q,-sC 2>/dev/null << EOF 
> print+(q=not =)[2==(()=<.* *>)].empty 
> EOF 
use File::Glob(); 
print((('not ')[(2 == (() = glob('.* *')))] . 'empty')); 

Oczywiście , to nie tworzy natychmiast "czytelnego" kodu, ale z pewnością przekształca niektóre z przeszkód.

+0

Heh. Żadna ilość odpychania nie usunie zaciemnienia użycia wartości logicznej do indeksu do anonimowej listy. [anti-pedantry: Tak, wiem, że "anonimowa lista" jest zbędna.] –

Powiązane problemy