Jak zastąpić trzecie wystąpienie ciągu w pliku za pomocą sed
polecenia.
Przykład:
Zmień tylko trzecie wystąpienie is
na us
w pliku.
Mój plik wejściowy zawiera:
hai this is linux.
hai this is unix.
hai this is mac.
hai this is unchanged.
Oczekuję, że wynikiem będzie:
hai this is linux.
hai thus is unix.
hai this is mac.
hai this is unchanged.
text-processing
sed
perl
Sureshkumar
źródło
źródło
sed
nie jest odpowiednim narzędziem do pracy.Odpowiedzi:
Łatwiej jest to zrobić
perl
.Aby zmienić 3 rd wystąpienie:
Aby zmienić co 3 rd wystąpienie:
źródło
Gdy zastępujący ciąg występuje tylko raz w linii, możesz łączyć różne narzędzia.
Gdy dane wejściowe znajdują się w pliku „input” i zastępujesz „is” przez „nas”, możesz użyć
źródło
is
na linię.Poniższy skrypt (wykorzystujący składnię GNU
sed
) nadaje się do edycji w miejscu, a nie do wydruku, ponieważ zatrzymuje pożądane wiersze po pożądanym podstawieniu:Jeśli podoba Ci się taka decyzja dotycząca choroby , możesz zmodyfikować powyżej
który wypisuje wszystkie linie
Lub musisz umieścić wszystkie linie w przestrzeni wzorów (w pamięci, więc uważaj na ograniczenie rozmiaru) i dokonaj podstawienia
źródło
Możesz tego użyć
sed
, jeśli wcześniej nowe znaki zostały zastąpione innymi znakami, np .:Podobnie jest z czystym (GNU)
sed
:(
sed
zamiennik nowej linii bezwstydnie skradziony z https://stackoverflow.com/a/1252191/4488514 )źródło
sed
składni specyficznej dla GNU , równie dobrze możesz użyćsed -z 's/is/us/3'
.-z
musi być nową funkcją,GNU sed version 4.2.1
nic nie wiem o tej opcji.\x0
kroku.Ta część
sed
po prostu przenosi liczbęis
wystąpień z jednej linii do drugiej. Powinien niezawodnie obsłużyć tyleis
esów w linii, ile w niego rzucisz, i nie musi buforować starych linii, podczas gdy to robi - zachowuje tylko jeden znak nowej linii dla każdegois
napotkanego, który nie jest częścią innego słowa.Rezultatem jest to, że zmodyfikuje tylko trzecie wystąpienie w pliku - i będzie przenosił liczbę na linię. Więc jeśli plik wygląda jak:
... wydrukuje ...
Najpierw obsługuje skrzynki na krawędziach, wstawiając odstęp na czubku i na końcu każdej linii. To sprawia, że granice słów są nieco łatwiejsze do ustalenia.
Następnie szuka poprawnych znaków,
is
wstawiając\n
ewline, zanim wszystkie jego wystąpieniais
poprzedzą zero lub jeden znak interpunkcyjny, a po nim spację. Robi kolejne przejście i usuwa wszystkie\n
owline, które są bezpośrednio poprzedzone znakiem spacji. Te pozostawione znaczniki będą pasowaćis.
, ais
jednak niethis
lub?is
.Następnie zbiera każdy znacznik na ogonie sznurka - za każde
\ni
dopasowanie w linii dołącza\n
ewlinię do ogona sznurka i zastępuje go jednymi
lubu
. Jeśli są 3\n
ewline w rzędzie zebrane na końcu sznurka, wówczas używa u - w przeciwnym razie i. Pierwsze użycie au jest również ostatnie - zamiennik uruchamia nieskończoną pętlę, która sprowadza się doget line, print line, get line, print line,
i tak dalej.Pod koniec każdego cyklu pętli próbnej czyści wstawione spacje, drukuje tylko do pierwszego występującego nowego wiersza w przestrzeni wzorów i wraca.
Dodam
l
polecenie ook na początku pętli, takie jak:... i zobacz, jak to działa, gdy działa z tymi danymi wejściowymi:
... więc oto, co robi:
Ma to większy sens, może z większą liczbą
is
es na linię:To praktycznie to samo, ale napisane w / POSIX BRE i podstawowa obsługa argumentów.
... dostaje ...
... a jeśli włączę
${dbg}
:... możemy obserwować iterację ...
źródło
Oto logiczne rozwiązanie, które używa
sed
itr
ale muszą być napisane w skrypcie do jego pracy. Poniższy kod zastępuje co 3 wystąpienie słowa określonego wsed
poleceniu. Wymieńi=3
sięi=n
do tej pracy dla każdegon
.Kod:
Dlaczego to działa:
Załóżmy, że plik tekstowy to
a b b b b a c a d a b b b a b e b z b s b a b
.Gdy n = 2: chcemy zastąpić co drugie wystąpienie
b
.a b b b b a c a d a b b b a b e b z b s b a b
. . ^ . ^ . . . . . . ^ . . ^ . . . ^ . ^ . ^
Gdy n = 3: chcemy zastąpić co trzecie wystąpienie
b
.a b b b b a c a d a b b b a b e b z b s b a b
. . . ^ . . . . . . . ^ . . . . ^ . . . . . ^
Gdy n = 4: chcemy zastąpić co trzecie wystąpienie
b
.źródło