Dokumentacja POSIX sed mówi:
Funkcja może być poprzedzona jednym lub więcej „!” znaki, w którym to przypadku należy zastosować funkcję, jeśli adresy nie wybierają przestrzeni wzorca. Zero lub więcej <blank> znaków zostanie zaakceptowanych przed pierwszym „!” postać. Nie jest określone, czy znaki <blank> mogą występować po znaku „!” znak, a zgodne aplikacje nie powinny występować po znaku „!” znak ze znakami <blank>.
Tak więc, przy pomocy dowolnego POSIX sed, możemy:
sed -e '/pattern/!d' file
To tak samo jak pisanie:
sed -e '/pattern/!!d' file
A !!!d
i n
od wykrzykniki są nadal będzie dobrze (testowane z trzech sed
wersji z scheda Biblioteka szablonów ). Nie widzę żadnej korzyści między wielokrotnością zamiast jednego wykrzyknika.
Dlaczego specyfikacja zezwala na tę składnię i jak jest przydatna w aplikacjach w świecie rzeczywistym?
Wygląda na to, że GNU sed nie jest w tym przypadku zgodny, będzie narzekać, jeśli użyjemy wielu wykrzykników:
$ sed -e '/pattern/!!d' file
sed: -e expression #1, char 11: multiple `!'s
!
działa jak przełącznik,/pattern/!!
jest taki sam jak/pattern/
i/pattern/!!!
jest taki sam jak/pattern/!
. Na FreeBSD wiele!
jest takich samych jak jeden.sed
można generować skrypty . Biorąc pod uwagę POSIXsed
, napisaniesed
skryptu powinno być naprawdę prostą sprawą . I tak, jeśli masz jakiś wyzwalacz dla jakiegoś przypadku, który powinien oznaczać adres!
niegodny tego, czym była twoja akcja, możesz nawet uruchomić to wiele razy dla tego samego i nadal wychodzić z tymi samymi rezultatami.sed
nie są.Odpowiedzi:
sed
Interfejs API jest prymitywny - i to z założenia. Przynajmniej pozostał prymitywny z założenia - nie wiem, czy został zaprojektowany pierwotnie od samego początku. W większości przypadków napisaniesed
skryptu, który po uruchomieniu wygeneruje innysed
skrypt, jest w rzeczywistości prostą sprawą.sed
jest bardzo często stosowany w ten sposób przez preprocesory makr, takie jakm4
i / lubmake
.(Poniżej znajduje się wysoce hipotetyczny przypadek użycia: jest to problem zaprojektowany w celu dopasowania do rozwiązania. Jeśli wydaje ci się, że jest to rozciągnięcie, prawdopodobnie jest tak, ponieważ tak jest, ale niekoniecznie czyni go mniej ważnym.)
Rozważ następujący plik wejściowy:
Gdybyśmy chcieli napisać
sed
skrypt, który dołączałby słowo- literę do ogona każdego odpowiedniego słowa w powyższym pliku wejściowym tylko wtedy, gdyby można go było znaleźć w wierszu w odpowiednim kontekście , i chcieliśmy to zrobić tak efektywnie, jak to możliwe ( co powinno być naszym celem, na przykład podczas operacji kompilacji) , powinniśmy raczej unikać stosowania/
wyrażeń regularnych w/
jak największym stopniu.Jedną z rzeczy, które moglibyśmy zrobić, jest wstępna edycja pliku w naszym systemie i nigdy nie wywoływać
sed
w ogóle podczas kompilacji. Ale jeśli którekolwiek z tych słów w pliku powinno lub nie powinno być uwzględnione w oparciu o ustawienia lokalne i / lub opcje czasu kompilacji, to prawdopodobnie nie byłoby pożądaną alternatywą.Inną rzeczą, którą moglibyśmy zrobić, to przetworzenie pliku teraz na wyrażenie regularne. Możemy stworzyć - i dołączyć do naszej kompilacji -
sed
skrypt, który może wprowadzać zmiany zgodnie z numerem linii - co w dłuższej perspektywie jest zazwyczaj znacznie wydajniejszą trasą.Na przykład:
... który zapisuje dane wyjściowe w postaci
sed
skryptu i który wygląda jak ...Gdy dane wyjściowe są zapisywane w wykonywalnym pliku tekstowym na moim komputerze o nazwie
./bang.sed
i działają tak./bang.sed ./infile
, dane wyjściowe są następujące:Teraz możesz mnie zapytać ... Dlaczego miałbym to zrobić? Dlaczego nie miałbym po prostu dopasowywać
grep
zapałek? Kto w ogóle używa futerału na wielbłądy? I na każde pytanie mogłem tylko odpowiedzieć, nie mam pojęcia ... ponieważ nie mam. Przed przeczytaniem tego pytania nigdy osobiście nie zauważyłem multi-! wymaganie analizy w specyfikacji - myślę, że to całkiem fajny haczyk.Multi-! rzecz nie od razu dla mnie sensu, choć - znaczna część
sed
specyfikacji jest nastawiona prostu analizowany i po prostu generowanychsed
skryptów. Prawdopodobnie znajdziesz w tym kontekście wymagane\n
ograniczniki ewline, które[wr:bt{]
mają o wiele więcej sensu, a jeśli będziesz pamiętać o tym pomyśle, możesz lepiej zrozumieć inne aspekty specyfikacji - (takie jak:
brak akceptacji adresów iq
odmowa zaakceptować więcej niż 1) .W przykładzie powyżej piszę z pewną formę
sed
skryptu, który może tylko kiedykolwiek być odczytywane raz. Jeśli przyjrzysz się temu uważnie, zauważysz, że podczassed
odczytywania pliku edycji przechodzi on od jednego bloku poleceń do następnego - nigdy nie rozgałęzia się ani nie kończy skryptu edycji, dopóki nie przejdzie do końca z plikiem edycji.Uważam to za multi-! adresy mogą być bardziej przydatne w tym kontekście niż w niektórych innych, ale szczerze mówiąc, nie mogę wymyślić jednego przypadku, w którym mógłbym bardzo dobrze je wykorzystać - i to
sed
bardzo często. Myślę też, że warto zauważyć, żesed
oba GNU / BSD nie radzą sobie z tym, jak podano - prawdopodobnie nie jest to aspekt specyfikacji, który jest bardzo pożądany, więc jeśli implementacja przeoczy ją, wątpię bardzo poważnie, że ich błędy @ box będą cierpieć strasznie w rezultacie.To powiedziawszy, brak obsługi tego, jak określono, jest błędem dla dowolnej implementacji, która udaje zgodność, dlatego myślę, że należy wysłać wiadomość e-mail do odpowiednich skrzynek programistycznych i zamierzam to zrobić, jeśli nie.
źródło
!
zostanie usuniętych w następnej specyfikacji , co się tutaj dzieje!