Kiedy przesyłam potokiem wiele poleceń uniksowych, takich jak grep, sed, tr itp., Mam tendencję do określania pliku wejściowego, który jest przetwarzany za pomocą cat. Coś w stylu cat file | grep ... | awk ... | sed ...
.
Ale ostatnio po kilku komentarzach do moich odpowiedzi wskazujących, że było to bezużyteczne użycie kota, pomyślałem, że zadam pytanie tutaj.
Przejrzałem problem i natknąłem się na artykuł Wikipedii na temat UUOC i nagrody The Useless Use of Cat Award i wydaje mi się, że przedstawione argumenty są z punktu widzenia wydajności.
Najbliższe pytanie, jakie tu spotkałem, brzmiało: Czy marnotrawić nazywać kota? - ale nie do końca o to pytam.
Myślę, że to, co sugeruje obóz UUOC, to użycie cmd1 args < file | cmd2 args | cmd3 ..
lub jeśli polecenie ma opcję odczytu z pliku, a następnie przekazania pliku jako argumentu.
cat file | cmd1 ... | cmd2
Wydaje mi się jednak o wiele łatwiejsze do odczytania i zrozumienia. Nie muszę pamiętać różnych sposobów wysyłania plików wejściowych do różnych poleceń, a proces przebiega logicznie od lewej do prawej. Najpierw dane wejściowe, potem pierwszy proces ... i tak dalej.
Czy nie rozumiem, jakie są argumenty na temat bezużytecznego korzystania z kota? Rozumiem, że jeśli uruchamiam zadanie crona, które uruchamia się co 2 sekundy i wymaga dużo przetwarzania, wtedy kot może być marnotrawstwem. Ale poza tym jaki jest ogólny konsensus w sprawie korzystania z kota?
źródło
< file cmd1 args | cmd2 args ...
też działa ... więc twój argument „od lewej do prawej ” jest nieważny. Często używam tego dla jasności - kolejność, którą pokazałem, może powodować, że ludzie się zatrzymują, co nie jest dobre. Im większa liczba wątków staje się normą, tym mniej staje się problemem IMO ...Odpowiedzi:
Jest bezużyteczny w tym sensie, że używanie go w ten sposób niczego nie osiąga, czego inne, być może bardziej wydajne opcje nie mogą (tj. Wytwarzanie właściwych wyników).
Ale
cat
jest o wiele potężniejszy niż tylkocat somefile
. Sprawdźman cat
lub przeczytaj, co napisałem w tej odpowiedzi . Ale jeśli absolutnie pozytywnie potrzebujesz tylko zawartości jednego pliku, możesz uzyskać pewną przewagę wydajnościową, jeśli nie będziesz używaćcat
zawartości pliku.Jeśli chodzi o czytelność, zależy to od osobistych upodobań. Lubię
cat
wkładać pliki do innych poleceń z tego samego powodu, szczególnie jeśli aspekty wydajności są znikome.To zależy również od tego, co piszesz. Jeśli to twoja własna metoda powłoki i wygoda dla twojego komputera stacjonarnego, nikomu oprócz ciebie to nie będzie obchodzić. Jeśli natkniesz się na przypadek, w którym następnym narzędziem w łańcuchu lepiej byłoby szukać i rozpowszechniać to jako często używane oprogramowanie w minimalnym systemie Linux na mało wydajnym routerze lub podobnym urządzeniu z prawdziwymi ograniczeniami zdolność przetwarzania, to jest inne. Zawsze zależy od kontekstu.
źródło
W codziennym korzystaniu z wiersza poleceń niewiele się różni. Szczególnie nie zauważysz żadnej różnicy prędkości, ponieważ czas na procesorze unika się, gdy nie używasz
cat
, twój procesor będzie po prostu bezczynny. Nawet jeśli przeglądasz setki lub tysiące (a nawet setki tysięcy) przedmiotów z praktycznego punktu widzenia, nie będzie to miało większego znaczenia, chyba że używasz bardzo obciążonego systemu (Load Average / N CPU> 1).Miejsce, w którym guma styka się z drogą, polega na kształtowaniu dobrych nawyków i zniechęcaniu złych. Aby wyciągnąć spleśniały stereotyp, diabeł tkwi w szczegółach. I takie szczegóły oddzielają przeciętne od wielkich.
To jak podczas prowadzenia samochodu, po co skręcać w lewo, skoro zamiast tego możesz zrobić tylko trzy prawa? Oczywiście, że możesz i działa idealnie. Ale jeśli zrozumiałeś siłę skrętów w lewo, trzy prawa wydają się po prostu głupie.
Nie chodzi o oszczędzanie jednego uchwytu pliku, 17k pamięci RAM i 0,004 sekundy czasu procesora. Chodzi o całą filozofię korzystania z UNIX. „Moc skrętów w lewo” na mojej ilustracji to nie tylko przekierowywanie danych wejściowych, to filozofia UNIX. Pełne rozwścieczenie sprawi, że osiągniesz lepszy wynik niż ci, którzy cię otaczają, i zyskasz szacunek tych, którzy rozumieją.
źródło
cat
Nie wyeliminuje podziału na strony, jednak przesyłanie potoków do czegoś może wyeliminować stronicowanie przez niektóre aplikacje.Często używam
cat file | myprogram
w przykładach. Czasami jestem oskarżany o bezużyteczne korzystanie z cat ( http://www.iki.fi/era/unix/award.html ). Nie zgadzam się z następujących powodów:Łatwo jest zrozumieć, co się dzieje.
Czytając polecenie UNIX, oczekujesz polecenia, po którym następują argumenty, a następnie przekierowanie. Możliwe jest umieszczenie przekierowania w dowolnym miejscu, ale rzadko się go widuje - dlatego ludzie będą mieli trudniej czytać przykład. wierzę
jest łatwiejszy do odczytania niż
Jeśli przeniesiesz przekierowanie na początek, mylisz osoby, które nie są przyzwyczajone do tej składni:
przykłady powinny być łatwe do zrozumienia.
Łatwo to zmienić.
Jeśli wiesz, że program może czytać od cat, możesz normalnie założyć, że może on odczytać dane wyjściowe z dowolnego programu, który wysyła dane do STDOUT, a zatem możesz dostosować go do własnych potrzeb i uzyskać przewidywalne wyniki.
Podkreśla, że program nie zawiedzie, jeśli STDIN nie jest zwykłym plikiem.
Nie jest bezpiecznie zakładać, że jeśli
program1 < foo
działa, tocat foo | program1
również będzie działać. Jednak to jest w praktyce bezpiecznie założyć odwrotnie. Ten program działa, jeśli STDIN jest plikiem, ale kończy się niepowodzeniem, jeśli wejście jest potokiem, ponieważ używa funkcji seek:Patrzyłem na obniżenie wydajności na http://oletange.blogspot.dk/2013/10/useless-use-of-cat.html Wniosek nie jest przydatny,
cat file |
jeśli złożoność przetwarzania jest podobna do zwykłego grep a wydajność ma większe znaczenie niż czytelność. W innych sytuacjachcat file |
jest w porządku.źródło
Myślę, że niektórzy komentujący coś, co jest UUOC, zajmują stanowisko, że jeśli naprawdę rozumiemy uniks i składnię powłoki, nie użyłby cat w tym kontekście. Jest to postrzegane jako użycie złej gramatyki: mogę napisać zdanie przy użyciu złej gramatyki i nadal rozumiem, ale wykazuję również słabe rozumienie języka i, co za tym idzie, słabą edukację. Więc powiedzenie, że coś jest UUOC, to inny sposób powiedzenia, że ktoś nie rozumie, co robi.
Jeśli chodzi o wydajność, jeśli wykonujesz potok z wiersza poleceń, wykonanie go przez maszynę zajmuje mniej czasu
cat somefile |
niż zastanowienie się, czy może być bardziej efektywny w użyciu< somefile
. To po prostu nie ma znaczenia.źródło
cat somefile | prog
w skorupce bez kota, na przykład,prog < somefile
ale zawsze wydawały mi się one w niewłaściwej kolejności, szczególnie z połączonym łańcuchem poleceń. Teraz widzę, że coś tak eleganckiego jak< somefile prog
ta sztuczka, dziękuję. Skończyły mi się wymówki, które zostawiłem, żeby użyć kota.Nagroda nie była mi znana do dziś, kiedy jakiś debiutant próbował przypiąć mi UUOC za jedną z moich odpowiedzi. To było
cat file.txt | grep foo | cut ... | cut ...
. Dałem mu trochę do myślenia i dopiero po tym, jak odwiedziłem ten link, podał mi, odnosząc się do pochodzenia nagrody i praktyki. Dalsze poszukiwania doprowadziły mnie do tego pytania. Niestety, pomimo świadomego przemyślenia, żadna z odpowiedzi nie zawierała mojego uzasadnienia.Nie chciałem być defensywny, kiedy go wychowywałem. W końcu w młodszych latach pisałbym to polecenie,
grep foo file.txt | cut ... | cut ...
ponieważ za każdym razem, gdy robisz częste singlegrep
, uczysz się umiejscowienia argumentu pliku i wiadomo, że pierwszy to wzorzec, a później nazwy plików.Był to świadomy wybór, kiedy odpowiedziałem na pytanie z
cat
prefiksem częściowo z powodu „dobrego smaku” (słowami Linusa Torvaldsa), ale głównie z ważnej przyczyny.Ten drugi powód jest ważniejszy, dlatego przedstawię go na pierwszym miejscu. Kiedy oferuję rurociąg jako rozwiązanie, spodziewam się, że będzie można go ponownie wykorzystać. Jest całkiem prawdopodobne, że rurociąg zostanie dodany na końcu lub połączony z innym rurociągiem. W takim przypadku posiadanie argumentu pliku do grep psuje możliwość ponownego użycia i całkiem możliwe, że robi to po cichu bez komunikatu o błędzie, jeśli argument pliku istnieje. I. e.
grep foo xyz | grep bar xyz | wc
da, ile w liniexyz
zawierająbar
natomiast spodziewasz liczbę wierszy, które zawierają zarównofoo
ibar
. Konieczność zmiany argumentów na polecenie w potoku przed jego użyciem jest podatna na błędy. Dodaj do tego możliwość cichych niepowodzeń, a stanie się to szczególnie podstępną praktyką.Ten pierwszy powód nie jest również nieistotny, ponieważ wiele „dobrego smaku” jest jedynie intuicyjnym podświadomym uzasadnieniem rzeczy takich jak ciche niepowodzenia powyżej, o których nie można pomyśleć w chwili, gdy ktoś potrzebujący edukacji mówi „ale nie jest ten kot bezużyteczny ”.
Spróbuję jednak również uświadomić dawny powód „dobrego smaku”, o którym wspomniałem. Ten powód ma związek z duchem ortogonalnego projektowania Uniksa.
grep
nie robicut
ils
nie robigrep
. Dlatego przynajmniejgrep foo file1 file2 file3
stoi w sprzeczności z duchem designu. Ortogonalnym sposobem na to jestcat file1 file2 file3 | grep foo
. Terazgrep foo file1
jest to tylko szczególny przypadekgrep foo file1 file2 file3
, a jeśli nie traktujesz go tak samo, przynajmniej zużywasz cykle zegara mózgowego, próbując uniknąć niepotrzebnej nagrody kota.To prowadzi nas do argumentu, który
grep foo file1 file2 file3
jest konkatenacją icat
konkatenacją, więc jest to słuszne,cat file1 file2 file3
ale ponieważcat
nie jest konkatenacja,cat file1 | grep foo
dlatego naruszamy ducha zarównocat
wszechmogącego, jak i wszechmogącego. Cóż, gdyby tak było, Unix potrzebowałby innego polecenia, aby odczytać wyjście jednego pliku i wypluć go na standardowe wyjście (nie dzieląc go na strony ani nic innego, jak czystą pracę na standardowe wyjście). Tak więc miałbyś sytuację, w której mówiszcat file1 file2
lub mówiszdog file1
i sumiennie pamiętasz, aby unikaćcat file1
unikania nagrody, jednocześnie unikając,dog file1 file2
ponieważ, miejmy nadzieję, projektdog
będzie powodował błąd, jeśli podano wiele plików.Mam nadzieję, że w tym momencie sympatyzujesz z projektantami uniksowymi, ponieważ nie zawarli osobnego polecenia wypluwania pliku na standardowe wyjście, jednocześnie nadając nazwę
cat
konkatenacji zamiast nadawać jej inną nazwę.<edit>
jest taki pies, niefortunny<
operator. Niefortunne jest jego umieszczenie na końcu rurociągu, uniemożliwiając łatwą kompozycję. Nie ma syntaktycznie ani estetycznie czystego sposobu umieszczenia go na początku. Niestety nie jest wystarczająco ogólny, więc zaczynasz od psa, ale po prostu dodajesz inną nazwę pliku, jeśli chcesz, aby była przetwarzana po poprzedniej. (Z>
drugiej strony nie jest w połowie tak źle. Ma prawie idealne położenie na końcu. Zazwyczaj nie jest to część rurociągu wielokrotnego użytku, a zatem wyróżnia się symbolicznie.)</edit>
Kolejne pytanie brzmi: dlaczego ważne jest, aby mieć komendy, które jedynie plują na plik lub łączą kilka plików na standardowe wyjście, bez dalszego przetwarzania? Jednym z powodów jest uniknięcie posiadania przez każdą pojedynczą komendę Uniksa, która działa na standardowym wejściu, aby wiedzieć, jak parsować przynajmniej jeden argument pliku wiersza poleceń i używać go jako danych wejściowych, jeśli istnieje. Drugim powodem jest uniknięcie przez użytkowników konieczności pamiętania: (a) gdzie idą argumenty nazwy pliku; oraz (b) unikać cichego błędu potoku, jak wspomniano powyżej.
To prowadzi nas do tego, dlaczego
grep
ma dodatkową logikę. Uzasadnieniem jest umożliwienie płynnej obsługi poleceń często używanych i autonomicznych (a nie potokowych). Jest to niewielki kompromis ortogonalności dla znacznego wzrostu użyteczności. Nie wszystkie polecenia powinny być zaprojektowane w ten sposób, a polecenia, które nie są często używane, powinny całkowicie unikać dodatkowej logiki argumentów pliku (pamiętaj, że dodatkowa logika prowadzi do niepotrzebnej niestabilności (możliwość błędu)). Wyjątkiem jest dopuszczenie argumentów pliku, tak jak w przypadkugrep
. (nawiasem mówiąc,ls
ma zupełnie inny powód, aby nie tylko akceptować, ale wymagać argumentów pliku)Wreszcie, lepiej byłoby, gdyby tak wyjątkowe polecenia, jak
grep
(ale niekonieczniels
) generowały błąd, jeśli standardowe wejście jest dostępne. Jest to uzasadnione, ponieważ polecenia zawierają logikę, która narusza ortogonalnego ducha wszechmogącego Uniksa dla wygody użytkownika. Aby zwiększyć wygodę użytkownika, tj. Aby zapobiec cierpieniu spowodowanemu przez cichą awarię, takie polecenia nie powinny wahać się naruszyć własnego naruszenia poprzez powiadomienie użytkownika, jeśli istnieje możliwość cichej awarii.źródło
grep pattern f1 f2 f3
nie jest to proste połączenie .grep
wie o plikach i drukuje nazwy plików (i opcjonalnie numery linii i cokolwiek innego).grep . /sys/kernel/mm/transparent_hugepage/*
to dobry hack do drukowania nazwy pliku: zawartość pliku z dużą ilością plików jednowierszowych. Klasyczny design Uniksa polega na tym, że większość narzędzi działa*.txt
bez potrzebycat
.cat
służy do spłaszczania wielu plików w jednym strumieniu.grep
przykładu takim programemcut
, który nie ma powodu, aby przejmować się wieloma plikami, i zawsze może być zasilany ze standardowego wejścia. Niektóre narzędzia, takie jaktr
, w ogóle nie akceptują argumentów plików i działają tylko jako filtry, więc wybór należy międzycat
i<
.<file cmd1 | cmd2 >out
przyznaję, że nie jest cudowne, ale można się do tego przyzwyczaić. Ciągle mówisz o „duchu wszechmogącego Unixa” w drwiący sposób, co zupełnie mi się nie podoba, ponieważ brzmi to tak, jakbyś nie rozumiał lub nie chciał, aby tak myśleli projektanci uniksowi. W porządku, jeśli nie podoba ci się uniksowy projekt, ale nie jest on z natury głupi. Nie jestem pewien, czy projekt systemu operacyjnego poprzedza składnię powłoki i jak to wszystko ewoluowało, ale dodatkowejcat
w 1970 roku warto było unikać!cat
pomaga w ponownym użyciu i łączeniu potoków, podczas gdy bez niego można uzyskać ciche awarie (wyszukaj „cicho” w mojej odpowiedzi).W obronie bezużytecznych zastosowań Cat
(Kilka akapitów, które pomogą zrównoważyć tsunami dokuczliwych komentarzy w stosunku do tej praktyki)
Używam basha przez zbyt wiele lat zarówno jako powłokę, jak i język skryptowy dla małych skryptów (a czasem z przykrością dla nie tak małych). Dawno, dawno temu dowiedziałem się o „Bezużytecznym użyciu kota” (UUoC). Nadal jestem tego winny przynajmniej co tydzień, ale szczerze mówiąc, rzadko czuję się nawet trochę zmuszony, aby tego uniknąć. Uważam, że używanie
cat
vs< file
polega bardziej na smaku niż różnicach technicznych i napisałem tę odpowiedź, aby chronić nowych użytkowników Linuksa, którzy podzielają mój gustcat
od myślenia, że jest coś poważnie złego w ich sposobie (i zwróć uwagę na kilka przypadków, w których jest). Podobnie jak Linus Torvalds, uważam również, że często smak jest ważniejszy niż umiejętność. Nie oznacza to, że mój gust jest lepszy od twojego, ale oznacza, że jeśli coś smakuje źle, nie zrobię tego bez zdobycia czegoś godnego.Jest już oczywiste, że podobnie jak autor pytania , czuję, że korzystanie z cat jest bardzo naturalne podczas pracy z REPL, takim jak bash, w którym badam problem poprzez stopniowe konstruowanie złożonych poleceń. Oto bardzo typowy przykład: mam plik tekstowy i niewiele o nim wiem. Napiszę,
cat file
aby poznać smak zawartości. Jeśli wyjście jest zbyt dużo będę uderzyłem strzałkę w górę i w zależności od okoliczności dodam| head
lub| grep foo
lub| what_ever
rozszerzenie mojego poprzedniego polecenia przez dodanie etapów obróbki. Ten sposób stopniowego przechodzenia od prostej komendy do bardziej złożonej przez dodanie jednego kroku przetwarzania po drugim jest dla mnie bardzo naturalny (robię to samo na ipython i uwielbiam sposóbpyfunctional
i podobne narzędzia programistyczne obejmują ten styl). Tak więc, pracując nad powłoką bash, jestem pewien, że przerwanie mojego przepływu w celu usunięciacat
jest bardziej bezużyteczne niż na to pozwala i cierpi ... no cóż, w 99,9% przypadków nie ma żadnych konsekwencji.Oczywiście przy pisaniu skryptów rzeczy mogą się zmienić. Ale nawet podczas pisania skryptów uważam, że ludzie, którzy kpią z UUoC, ignorują te ważne lekcje przez wielki umysł: „Przedwczesna optymalizacja jest źródłem wszelkiego zła” . A jeśli nie robisz czegoś nietypowego, naprawdę trudno jest UUoC być miejscem, w którym konieczna będzie optymalizacja. Oczywiście zdecydowanie musisz wiedzieć, co jest nieefektywne (to dodatkowe wywołanie procesu BTW, ponieważ niewielu zdaje się o tym wspominać). Mając tę wiedzę, jeśli zdarzy ci się pracować na tych rzadkich systemach, w których wywoływanie procesu jest kosztowne (np. Niektóre systemy osadzone lub CygWin w mniejszym stopniu), będziesz wiedział, co zrobić, jeśli wymaga tego specjalna sytuacja. Na przykład, jeśli dzwonisz
cat
wiele razy na sekundę w pętli (BTW, jeśli znajdziesz się w tej pozycji, zadaj sobie pytanie, czy bash jest właściwym narzędziem do pracy). Znowu jednak: „najpierw spraw, aby działał poprawnie, a następnie zoptymalizuj go w razie potrzeby” .Jak wyjaśnisz tsunami skarg na UUoC Nick?
Poza tym, że nie wszyscy mają mój gust, uważam, że główna część tego, dlaczego tak wielu ludzi narzeka na UUoC, nie jest techniczna, ale ludzka: większość nowicjuszy w Uniksie nie będzie wiedziała o tym
< file command
idiomie, więc pokusa bardziej doświadczonej osobie gry w „Old Guru” „ do nich. Będzie miał również okazję użyć fantazyjnych słów („wywołanie procesu”) i dotknąć drogiego tematu „optymalizacji”. Dobre wrażenie jest gwarantowane, więc bardzo trudno się oprzeć. Następnie nowicjusze skorzystają z rady Guru za dobrą monetę i przez długi czas będą odtwarzać ją innym jako „Jedyną Prawdę” (i głosują na poniższą odpowiedź :-). Zabawna uwaga: prawdopodobnie tak łatwo jest naprawić bash, aby uniknąć nieefektywności UUoC, że trzeba się zastanawiać, dlaczego nikt nie dodał tej funkcji ani nie zrobił< filename
cat plik po tylu latach. Ciemna dusza sugerowałaby, że niektórzy hakerzy z szarobrodym uderzają, by zostawić okazję, aby nas wyśmiewać ;-)źródło
Naprawdę fajna byłaby powłoka obsługująca składnię, taką jak:
Tymczasem uważam, że
cat filename | realcmd1...
jest to do przyjęcia, ponieważ utrzymuje standardową składnię za pomocą poleceń początkowych wymagających nazwy pliku jako argumentu.źródło
< filename cmd | cmd2 ...
. Czy to wystarczająco blisko?< file command ...
co najmniej od połowy lat 80. i prawdopodobnie już w latach 70., kiedysh
napisano oryginał . Mówiąc bardziej ogólnie, przekierowania we / wy są analizowane od lewej do prawej i mogą być przeplatane w dowolnej kolejności w wierszu polecenia.cmd <file arg arg...
Byłoby więc również ważne.Wszystkim, którzy twierdzą, że kota można używać, ponieważ „pachnie” lepiej lub „jest bardziej czytelny”, powiedziałbym tylko:
Dla ciebie może ... ale nie dla innych, którzy mogą przeczytać lub spróbować zrozumieć twój kod. Jeśli nigdy nie będziesz próbował instruować innych swoimi przykładami lub dzielić się swoim kodem, skorzystaj z niego w dowolnej chwili.
Dodam również ten komentarz, ponieważ od dawna użytkownik Linuksa i Administrator / Inżynier ... (i jest nas wielu) powoduje to, że widzimy, jak krwawią nam oczy. Czemu? Ponieważ wykorzystuje zasoby w systemach, na których ściśle kontrolujemy zasoby. Polecenie cat i sama potok używają dodatkowej pamięci i uchwytów plików, które są całkowicie bezużyteczne. Związałeś zasoby, których mój system potrzebuje za darmo, i nie zyskałeś NIC, co mogłoby wyjaśnić wykorzystanie tych zasobów. To jest ogromne nie nie.
Teraz mogę siedzieć tutaj i dyskutować z kimś przez cały dzień o zapachu kodu lub czytelności, ale na koniec jest to kwestia pisania lub niepoprawnego użycia i za każdym razem, gdy korzystasz z zasobów w systemie i nie zyskujesz na tym nic ... to jest złe.
Jako użytkownik domowy możesz uczyć się z moich rad i nauczyć się lepszych sposobów robienia rzeczy lub możesz zostać zaślepiony „zapachem” kotów, twoim wyborem ... ale wiedz, że jeśli otwarcie skorzystasz z tej praktyki, zostaniesz powołany na tej praktyce przez cały czas i będziecie musieli po cichu przyznać, że mają rację i jesteście uparci, ponieważ to prawda. :-)
źródło
cat foo.txt | ...
. Druga odpowiedź dobrze wyjaśnia, dlaczego może to być dobre wykorzystanie. Proste streszczenie sprawy na korzyść brzmi: „$ CPU time << $ Brain time” (jak skomentował @MikeP powyżej).