Zauważyłem, że jeśli dodam \n
do wzorca w celu podstawienia za pomocą sed
, to nie pasuje. Przykład:
$ cat > alpha.txt
This is
a test
Please do not
be alarmed
$ sed -i'.original' 's/a test\nPlease do not/not a test\nBe/' alpha.txt
$ diff alpha.txt{,.original}
$ # No differences printed out
Jak mogę to uruchomić?
sed
regular-expression
utilities
Belmin Fernandez
źródło
źródło
Odpowiedzi:
W najprostszym wywołaniu sed ma on jedną linię tekstu w przestrzeni wzorów, tj. 1 wiersz
\n
tekstu oddzielonego od danych wejściowych. Pojedyncza linia w przestrzeni wzorów nie ma\n
... To dlatego wyrażenie regularne niczego nie znajduje.Możesz odczytywać wiele wierszy w przestrzeni wzorców i manipulować rzeczami zaskakująco dobrze, ale z większym niż zwykle wysiłkiem. Sed ma zestaw poleceń, które pozwalają na tego typu rzeczy ... Oto link do Podsumowania poleceń dla sed . Jest to najlepszy, jaki znalazłem i sprawił, że się potoczyłem.
Zapomnij jednak o idei „one-liner”, kiedy zaczniesz używać mikro-poleceń sed. Przydatne jest rozplanowanie go jak ustrukturyzowanego programu, dopóki go nie poczujesz ... Jest zaskakująco prosty i równie niezwykły. Możesz myśleć o tym jako o „języku asemblera” edycji tekstu.
Podsumowanie: Używaj sed do prostych rzeczy, a może nieco więcej, ale ogólnie rzecz biorąc, gdy wykracza to poza pracę z jedną linią, większość ludzi woli coś innego ...
Pozwolę komuś innemu zasugerować coś innego. naprawdę nie jestem pewien, jaki byłby najlepszy wybór (użyłbym sed, ale to dlatego, że nie znam wystarczająco dobrze perla).
Tutaj jest ten sam skrypt, zagęszczony do tego, co oczywiście jest trudniejsze do czytania i pracy, ale niektórzy wątpliwie nazwaliby jedną linijkę
Oto moje polecenie „ściągawka”
źródło
t
tutaj polecenia - gdy nie otrzyma etykiety, domyślnie rozgałęzia się do końca skryptu. Taksed '/^a test$/{$!{N;s/^a test\nPlease do not$/not a test\nBe/;t;P;D}}' alpha.txt
robi dokładnie to samo polecenie w każdych okolicznościach. Oczywiście dla tego konkretnego plikused '/test/{N;s/.*/not a test\nBe/}' alpha.txt
robi to samo, ale mój pierwszy przykład jest logicznie równoważny dla wszystkich możliwych plików. Zauważ też, że\n
w ciągu zastępującym nie powstaje nowa linia; potrzebujesz do tego ukośnika odwrotnego `\ ', a po nim nowego wiersza.#
polecenie nie jest oddzielone od poprzedniego,\n
w RHS zs
). W GNUsed
możesz także używać-z
rekordów rozdzielanych przez NUL (a następnie zamazywać całe wejście, jeśli jest to tekst (który z definicji nie zawiera NUL).Użyj
perl
zamiastsed
:-pi -e
jest standardową sekwencją wiersza poleceń „zamień na miejscu”, a -0777 powoduje, że perl cały plik jest w porządku. Zobacz perldoc perlrun, aby dowiedzieć się więcej na ten temat.źródło
sed
i pojawiają się odpowiedzi przy użyciu awk lub perl. Myślę, że to nie jest na temat, dlatego przepraszam, ale zwolniłem jeden minus.sed
powyższa odpowiedź dowodzi, że odpowiedź Perla dotyczy tematu.Myślę, że lepiej jest zastąpić
\n
symbol innym symbolem, a następnie działać jak zwykle:np. nieobsługiwany kod źródłowy:
można zmienić na:
Jeśli ktoś nie wie,
\n
to kończy się linia UNIX,\r\n
- Windows,\r
- klasyczny Mac OS. Normalny tekst w systemie UNIX nie używa\r
symbolu, więc można go bezpiecznie używać w tym przypadku.Możesz także użyć jakiegoś egzotycznego symbolu, aby tymczasowo zastąpić \ n. Na przykład - \ f (symbol wysuwu formularza). Możesz znaleźć więcej symboli tutaj .
źródło
\r
w argumencie dosed
z$(printf '\r')
.$
przed sedem, aby zapobiec konwersji\r
pliku nar
. Krótki przykład:sed $'s/\r/~/'
. Pełny przykład:cat alpha.txt | tr '\n' '\r' | sed $'s/a test\rPlease do not/not a test\rBe/' | tr '\r' '\n'
Biorąc wszystko pod uwagę, pożeranie całego pliku może być najszybszym sposobem.
Podstawowa składnia jest następująca:
Pamiętaj, że pożeranie całego pliku może nie być opcją, jeśli plik jest ogromnie duży. W takich przypadkach inne podane tutaj odpowiedzi oferują niestandardowe rozwiązania, które z pewnością będą działać na małej przestrzeni pamięci.
We wszystkich innych sytuacjach hackowania i slashowania,
-e '1h;2,$H;$!d;g'
po prostu poprzedzanie, po którym następuje oryginalnysed
argument wyrażenia regularnego, prawie kończy zadanie.na przykład
Co ma
-e '1h;2,$H;$!d;g'
zrobić?1
,2,$
,$!
Części są linia projektantom ten limit, który wyściełającej bezpośrednio następujące polecenie działa na.1
: Tylko pierwsza linia2,$
: Wszystkie linie zaczynające się od drugiej$!
: Każda linia inna niż ostatniaTak rozszerzone, to dzieje się w każdym wierszu wejścia linii N.
g
Komenda nie została podana specyfikator linia, ale poprzedzająced
komenda ma specjalną klauzulę „ start następnego cyklu. ”, A to zapobiegag
uruchamianiu na wszystkich liniach oprócz ostatniego.Co do znaczenia każdego polecenia:
h
następnieH
s na każdej kopii wiersza powiedział linie wejściowesed
„s hold przestrzeni . (Pomyśl o dowolnym buforze tekstowym.)d
odrzuca każdą linię, aby zapobiec zapisaniu tych linii na wyjściu. Miejsce do przechowywania jest jednak zachowane.g
przywraca akumulację każdej linii z przestrzeni wstrzymania, dzięki czemused
jest w stanie uruchomić wyrażenie regularne na całym wejściu (a nie w sposób liniowy na raz), a zatem może dopasuj na\n
s.źródło
sed
posiada trzy polecenia do zarządzania działaniami multi-line:N
,D
iP
(je porównać do normalnegon
,d
ip
).W takim przypadku możesz dopasować pierwszy wiersz wzoru, użyć,
N
aby dołączyć drugi wiersz do obszaru wzorów, a następnie użyć,s
aby wykonać zamianę.Coś jak:
źródło
G
,H
,x
...). Za pomocąs
polecenia można również dodać więcej linii do obszaru wzorów .N
poleceńMożesz, ale to trudne . Polecam przejście na inne narzędzie. Jeśli istnieje wyrażenie regularne, które nigdy nie pasuje do żadnej części tekstu, który chcesz zastąpić, możesz użyć go jako separatora rekordów awk w GNU awk.
Jeśli nigdy nie ma dwóch kolejnych wierszy w ciągu wyszukiwania, możesz użyć „trybu akapitowego” awk (jeden lub więcej pustych wierszy oddzielnych rekordów).
Łatwym rozwiązaniem jest użycie Perla i pełne załadowanie pliku do pamięci.
źródło
perl -0777 -pe '…' <input-file >output-file
. Aby zmodyfikować plik na miejscu,perl -0777 -i -pe '…' filename
sed
„s-z
opcję (dodane w 2012 roku po tym, że odpowiedź została wysłana)seq 10 | sed -z 's/4\n5/a\nb/'
.Myślę, że to sed rozwiązanie dla 2 linii dopasowania.
Jeśli chcesz dopasować 3 linie, to ...
Jeśli chcesz dopasować 4 linie, to ...
Jeśli część zamienna w poleceniu „s” zmniejsza linie, jest to nieco bardziej skomplikowane
Jeśli część zamieniająca rośnie w linie, jest to nieco bardziej skomplikowane
źródło
Tutaj
/a test/,/Please do not/
jest uważany za blok tekstu (wieloliniowego),c
jest to polecenie zmiany, po którym następuje nowy tekstnot a test \nBe
W przypadku, gdy tekst, który ma zostać zastąpiony, jest bardzo długi, sugerowałbym składnię ex .
źródło
Po prostu poszerz nieco okno przy wejściu.
To całkiem proste. Oprócz standardowej substytucji; trzeba tylko
$!N
,P
iD
tu.źródło
Oprócz Perla, ogólne i przydatne podejście do edycji wieloliniowej dla strumieni (i plików również) to:
Najpierw utwórz nowy separator linii UNIQUE, jak chcesz, na przykład
Następnie w poleceniu sed (lub dowolnym innym narzędziu) zamieniasz \ n $ $ S, np
(awk zamienia separator linii ASCII na twój i odwrotnie.)
źródło
To jest mała modyfikacja sprytnej odpowiedzi Xary, aby działała na OS X (używam 10.10):
Zamiast jawnego używania
\r
, musisz użyć$(printf '\r')
.źródło
printf '\r'
(lubecho -e '\r'
) działają poprawnie, pamiętaj, że możesz po prostu użyć składni powłoki,$'\r'
aby odwoływać się do liter dosuniętych. Na przykład,echo hi$'\n'there
echo nowej linii pomiędzyhi
ithere
. Podobnie możesz owinąć cały ciąg, aby każdy ukośnik\
uniknął kolejnego znaku:echo $'hi\nthere'
Chciałem dodać kilka linii HTML do pliku za pomocą sed (i skończyłem tutaj). Zwykle używałbym perla, ale byłem na pudełku, które miało sed, bash i niewiele więcej. Odkryłem, że jeśli zmienię ciąg na jedną linię i pozwolę interpolować bash / sed, \ t \ n wszystko się ułoży:
Lepiej byłoby mieć funkcję pozwalającą uniknąć podwójnych cudzysłowów i ukośników, ale czasem abstrakcja jest złodziejem czasu.
źródło
GNU
sed
ma-z
opcję, która pozwala na użycie składni, którą OP próbował zastosować. ( strona podręcznika )Przykład:
Pamiętaj: jeśli używasz,
^
a$
teraz pasują do początku i końca linii rozdzielonych znakiem NUL (nie\n
). I, aby upewnić się, że dopasowania we wszystkich (\n
-separatowanych) liniach są podstawione, nie zapomnij użyćg
flagi do globalnych podstawień (nps/.../.../g
.).Kredyty: @ stéphane-chazelas po raz pierwszy wspomniał o -z w powyższym komentarzu.
źródło
Sed przerywa wprowadzanie nowych linii. Utrzymuje tylko jedną linię na pętlę.
Dlatego nie ma możliwości dopasowania
\n
(nowej linii), jeśli przestrzeń wzorcowa go nie zawiera.Istnieje jednak sposób, aby przy pomocy pętli sed mógł zachować dwie kolejne linie w przestrzeni wzorów:
Dodaj wymagane przetwarzanie między N i P (zastępując
l
).W tym przypadku (2 linie):
Lub dla trzech linii:
Zakłada się, że ta sama liczba linii zostanie zastąpiona.
źródło