Chciałbym użyć sed
lub perl
zastąpić wszystkie wystąpienia słowa, które nie ma określonego słowa przed nim.
Na przykład mam plik tekstowy, który zawiera fabułę filmu i chcę zastąpić wszystkie wystąpienia nazwiska postaci ich imieniem, ale tylko wtedy, gdy ich imię nie pojawi się bezpośrednio przed imieniem.
Przykładowy tekst może wyglądać następująco:
John Smith and Jane Johnson talk about Smith's car.
Chcę, aby wyglądało to tak:
John Smith and Jane Johnson talk about John's car.
Gdybym tak zrobił sed 's/Smith/John/' file
, miałbym:
John John and Jane Johnson talk about John's car.
Imię poprzedzające nazwisko zawsze będzie takie samo. Nie mam do czynienia z John Smith
i Frank Smith
. Potrzebuję tylko sposobu dopasowania Smith
, który nie ma John
go wcześniej.
sed
regular-expression
perl
jonescb
źródło
źródło
Odpowiedzi:
Byłoby łatwo w każdym języku, w którym wyrażenia regularne mogłyby wyglądać za sobą. Oczywiście Perl jest pierwszym na liście:
Słabym punktem jest posiadanie więcej niż jednego nie-słownego znaku między „John” i „Smith”. Niestety kwantyfikator jak
+
dla\W
podniosłoby „zmiennej długości nie lookbehind realizowane” błąd.źródło
EDYTUJ … ponownie twój komentarz .. Oto nowy skrypt, który nie dotyczy (np.) Williama Smitha. Tymczasowo zaciemnia wzory, które zachowuje jako Smith (niezmieniony).
Jeśli martwisz się o pana Pana ... to działa.
Możesz zaspokoić Williama , dodając jego nazwisko do listy lub , np.
sed -r 's/\<(William|John|...
To jest oryginalny skrypt
źródło
() Przechwyci nie-imię przed LastName, więc zostaną zastąpione ponownie.
Edytować
@ manatwork, gilles
Masz rację. Co powiesz na
To wydaje się załatwić sprawę.
źródło
[^John]
dopasowuje jeden znak, który musi być jednym zJ
,o
,h
lubn
. Wątpię, żeby to było to, co zamierzałeś. W wyrażeniach regularnych nie ma konstrukcji negacji (Perl ma(?!…)
i(?<!…)
, ale jeśli uważasz to za negację, prawdopodobnie nie zrobi tego, czego oczekujesz).sed
jej bez powoduje rozdętą logikę sed ...temp1
prawie zawsze będzie dobrze, ale! uważaj na ten autobus. Aby zminimalizować tę możliwość, uważam, że lepiej jest używać znaków, które (prawie) nigdy nie występują w plikach tekstowych łacińskich, np. Wartość szesnastkowa \ x01 \ x02, lub ich kombinacje, a może \ xe188b4 ustawienia regionalne UTF-8 (ሴ - ETHIOPIC SYLLABLE SEE) .. np.echo -e 'Z' |sed 's/./\xe1\x88\xb4/'
=>ሴ
gdy ustawieniem