Rozważ następujący plik wejściowy:
1
2
3
4
Bieganie
{ grep -q 2; cat; } < infile
nic nie drukuje. Spodziewałbym się, że to wydrukuje
3
4
Mogę uzyskać oczekiwany wynik, jeśli zmienię go na
{ sed -n 2q; cat; } < infile
Dlaczego pierwsze polecenie nie wypisuje oczekiwanego wyniku?
Jest to widoczny plik wejściowy i zgodnie ze standardem w OPCJACH :
-q
Quiet. Nothing shall be written to the standard output, regardless of
matching lines. Exit with zero status if an input line is selected.
i dalej, w części UŻYWANIE APLIKACJI (podkreśl moje):
Ta
-q
opcja umożliwia łatwe określenie, czy wzorzec (lub łańcuch) istnieje w grupie plików. Podczas przeszukiwania kilku plików zapewnia poprawę wydajności ( ponieważ może wyjść, gdy tylko znajdzie pierwsze dopasowanie ) [...]
Teraz, zgodnie z tym samym standardem (we wstępie , w obszarze PLIKI WEJŚCIOWE )
Gdy standardowe narzędzie odczytuje widoczny plik wejściowy i kończy się bezbłędnie, zanim osiągnie koniec pliku, narzędzie musi upewnić się, że przesunięcie pliku w otwartym opisie pliku jest właściwie ustawione tuż za ostatnim bajtem przetworzonym przez narzędzie [. ..]
tail -n +2 file
(sed -n 1q; cat) < file
...
Drugie polecenie jest równoważne pierwszemu tylko wtedy, gdy plik jest widoczny.
Dlaczego grep -q
zużywa cały plik?
Ma gnu grep
to znaczenie (choć Kusalananda właśnie potwierdził, że to samo dzieje się na OpenBSD)
grep
to rozwidlenie czegoś zwanego FreeGrep , jeśli ktoś się zastanawia.Odpowiedzi:
grep
zatrzymuje się wcześnie, ale buforuje dane wejściowe, więc test jest za krótki (i tak, zdaję sobie sprawę, że mój test jest niedoskonały, ponieważ nie można go zobaczyć):zaczyna się o 6776 w moim systemie. Odpowiada to buforowi 32KiB używanemu domyślnie w GNU grep:
wyjścia
Zauważ, że POSIX wspomina tylko o poprawie wydajności
To nie stawia żadnych oczekiwań na poprawę wydajności z powodu częściowego odczytu jednego pliku.
źródło
Wynika to oczywiście z buforowania, które
grep
przyspiesza. Istnieją narzędzia zaprojektowane specjalnie do odczytu dowolnej liczby znaków i nie więcej. Jednym z nich jestexpect
:Nie mam systemu do wypróbowania tego, ale wierzę,
expect
że zje wszystko, dopóki nie napotka oczekiwanego ciągu (2
), a następnie zakończy działanie, pozostawiając resztę danych wejściowychcat
.źródło
Zmieszałeś sed i grep.
W przypadku komendy sed
-2q
mówi się, aby wyjść z bieżącej iteracji, jeśli w drugim wierszu-n
opcja mówi cicho, więc wszystkie linie zostaną wyświetlone po drugim.Polecenie grep jest domyślnie uruchamiane, aby wypisać wszystkie pasujące linie - ale
-q
opcja mówi, aby nie wypisywać niczego na standardowe wyjście. więc jeśli wejście zawiera „2”, będzie miało wartość wyjściową SUKCES, w przeciwnym razie BŁĄD. To, co to jest, zależy od systemu operacyjnego i powłoki. Tak więc zazwyczaj powinieneś sprawdzić, czy linia pasuje, sprawdzając wartość wyjściową procesu grep. Jest to przydatne w potoku, w którym chcesz wiedzieć, czy dane wejściowe zawierają pewną wartość jako test. Na przykładW tym przypadku tak naprawdę nie zależy nam na wyświetleniu wszystkich pasujących linii, zależy nam tylko na tym, czy przynajmniej jedna z nich istnieje.
report_crash_via_email
Proces / funkcja może następnie zgaśnie i ponownie otworzyć plik, czy nie.Jeśli chcesz, aby proces grep zatrzymał się po znalezieniu znaku „2” - domyślnie nie będzie sprawdzał każdej linii, aby sprawdzić, czy pasuje - musisz to powiedzieć. Do tego służy przełącznik wiersza poleceń
-m <value>
. Tak dla przypadkugrep -q -m1 2
.źródło
grep
ale to pytanie dotyczy czegoś bardziej subtelnego i ezoterycznego. Wygląda na to, że przeczytałeś pytanie zbyt szybko, aby zrozumieć rzeczywiste zachowanie, którego dotyczy zapytanie. Również GNUgrep
robi poszukiwania zatrzymania w przypadku korzystania z-q
(co jest dozwolone w cytat z specyfikacją POSIX): strona man dla państw GNU grep, że „Exit [S] natychmiast stanu zerowego jeżeli zostanie znaleziony” . FWIW, edytowałem twoje pytanie, aby pokazać, jak sformatować przyszłe posty. Witamy w Stack Exchange .grep
pyta się, czy w pliku istnieje „2”, nic więcej i nic więcej. Do tego momentu nie zachowuje się jaksed
i nie zużywa zapisów, a resztę pozostawia do dalszego przetwarzania. Czyta, dopóki nie wie, że jest „2” lub że nie ma, zamyka plik i zwraca wynik.grep
w rzeczywistości „zużywa cały plik” (ignorując kwestie związane z buforowaniem), jeśli szukany ciąg nie występuje w pliku (co można udowodnić tylko poprzez sprawdzenie całego pliku). Niezależnie od tego, odczyt pliku zatrzymuje się , plik jest zamykany, a SUKCES wraca.