Oryginalny plik
claudio
antonio
claudio
michele
Chcę zmienić tylko pierwsze wystąpienie „claudio” na „claudia”, więc wynik pliku
claudia
antonio
claudio
michele
próbowałem
sed -e '1,/claudio/s/claudio/claudia/' nomi
Ale dokonaj globalnej zamiany. Dlaczego?
info sed
: (0,/REGEXP/
: Numer linii 0 może być użyty w specyfikacji adresu,0,/REGEXP/
tak abysed
próbował dopasować REGEXP również w pierwszej linii wejściowej. Innymi słowy,0,/REGEXP/
jest podobnie1,/REGEXP/
, z tym wyjątkiem, że jeśli ADDR2 pasuje do pierwszego wiersza wejścia, formularz 0, / REGEXP / uzna, że kończy on zakres, podczas gdy formularz 1, / REGEXP / dopasuje początek jego zakresu i tym samym zwiększy zakres zakresu aż do drugiego wystąpienia wyrażenia regularnego)awk '/claudio/ && !ok { sub(/claudio/,"claudia"); ok=1 } 1' nomi
powinien zrobićOdpowiedzi:
Jeśli używasz GNU
sed
, spróbuj:sed
nie uruchamia sprawdzanie regex, który kończy się zasięg aż po wierszu rozpoczynającym tego zakresu.Z
man sed
(strona POSIX, moje podkreślenie):Za pomocą
awk
Zakresy
awk
pracy są bardziej zgodne z oczekiwaniami:Wyjaśnienie:
NR==1,/claudio/
Jest to zakres, który zaczyna się od linii 1, a kończy przy pierwszym wystąpieniu
claudio
.sub(/claudio/, "claudia")
Gdy jesteśmy w zasięgu, to polecenie zastępcze jest wykonywane.
1
Ten tajemniczy skrót tego awk do drukowania linii.
źródło
sed
.awk '!r && /claudio/ {sub(/claudio/,"claudia"); r=1} 1'
awk !x{x=sub(/claudio/,"claudia")}1
0,/claudio/
Oto 2 kolejne programowe wysiłki z sed: oba czytają cały plik w jednym ciągu, a wyszukiwanie zastąpi tylko pierwszy.
Z komentarzem:
źródło
Nowa wersja GNU
sed
obsługuje tę-z
opcję.Możesz użyć tej opcji, jeśli chcesz
sed
pracować na różnych liniach.zwraca
źródło
Możesz użyć
awk
flagi, aby sprawdzić, czy wymiana została już wykonana. Jeśli nie, kontynuuj:źródło
To naprawdę bardzo proste, jeśli skonfigurujesz tylko niewielkie opóźnienie - nie musisz sięgać po niewiarygodne rozszerzenia:
To po prostu odkłada pierwszą linię na drugą i drugą na trzecią itd.
Drukuje:
źródło
I jeszcze jedna opcja
Zaletą jest to, że używa podwójnego cudzysłowu, dzięki czemu można używać zmiennych wewnątrz, tj.
źródło
Można to również zrobić bez przestrzeni wstrzymania i bez powiązania wszystkich linii z przestrzenią wzorów:
Objaśnienie: Próbujemy znaleźć „claudio” i jeśli to zrobimy, przeskoczymy do małej pętli obciążenia drukowania między
:x
ibx
. W przeciwnym razie drukujemy i restartujemy skrypt z następną linią.źródło
źródło
Sumaryczny
Składnia GNU:
Lub nawet (użyć tylko jednego słowa, które ma zostać zastąpione:
Lub w składni POSIX:
działa na każdym sed, przetwarza tylko tyle wierszy, ile potrzeba do znalezienia pierwszego
claudio
, działa nawet, jeśliclaudio
znajduje się w pierwszym wierszu i jest krótszy, ponieważ używa tylko jednego ciągu wyrażeń regularnych.Szczegół
Aby zmienić tylko jedną linię , musisz wybrać tylko jedną linię.
Użycie
1,/claudio/
(z twojego pytania) wybiera:claudio
.Aby wybrać dowolny wiersz, który zawiera
claudio
:Aby wybrać tylko pierwszy
claudio
plik, użyj:Następnie możesz dokonać podstawienia tylko w tym wierszu:
Który zmieni tylko pierwsze wystąpienie dopasowania wyrażenia regularnego w linii, nawet jeśli może być więcej niż jeden, w pierwszym wierszu, który pasuje do wyrażenia regularnego.
Oczywiście
/claudio/
wyrażenie regularne można uprościć w celu:A zatem jedyne, czego brakuje, to wydrukowanie wszystkich pozostałych wierszy niezmodyfikowanych:
źródło