sedInterfejs 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 napisanie sedskryptu, który po uruchomieniu wygeneruje inny sedskrypt, jest w rzeczywistości prostą sprawą. sedjest bardzo często stosowany w ten sposób przez preprocesory makr, takie jak m4i / lub make.
(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:
cat <<"" >./infile
camel
cat dog camel
dog cat
switch
upper
lower
Gdybyśmy chcieli napisać sedskrypt, 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ć sedw 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 - sedskrypt, który może wprowadzać zmiany zgodnie z numerem linii - co w dłuższej perspektywie jest zazwyczaj znacznie wydajniejszą trasą.
Na przykład:
n=$(printf '\\\n\t')
grep -En 'camel|upper|lower' <infile |
sed " 1i${n%?}#!/usr/heirloom/bin/posix2001/sed -nf
s/[^:]*/:&$n&!n;&!b&$n&/;s/://2;\$a${n%?}q"'
s/ *cat/!/g;s/ *dog/!/g
s| *\([cul][^ ]*\).*|s/.*/\1-case/p|'
... który zapisuje dane wyjściowe w postaci sedskryptu i który wygląda jak ...
#!/usr/heirloom/bin/posix2001/sed -nf
:1
1!n;1!b1
1s/.*/camel-case/p
:2
2!n;2!b2
2!!s/.*/camel-case/p
:5
5!n;5!b5
5s/.*/upper-case/p
:6
6!n;6!b6
6s/.*/lower-case/p
q
Gdy dane wyjściowe są zapisywane w wykonywalnym pliku tekstowym na moim komputerze o nazwie ./bang.sedi działają tak ./bang.sed ./infile, dane wyjściowe są następujące:
camel-case
upper-case
lower-case
Teraz możesz mnie zapytać ... Dlaczego miałbym to zrobić? Dlaczego nie miałbym po prostu dopasowywać grepzapał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ęść sedspecyfikacji jest nastawiona prostu analizowany i po prostu generowanych sed skryptów. Prawdopodobnie znajdziesz w tym kontekście wymagane \nograniczniki 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 i qodmowa zaakceptować więcej niż 1) .
W przykładzie powyżej piszę z pewną formę sedskryptu, który może tylko kiedykolwiek być odczytywane raz. Jeśli przyjrzysz się temu uważnie, zauważysz, że podczas sedodczytywania 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 sedbardzo często. Myślę też, że warto zauważyć, że sedoba 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.
!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.