2014-04-17 14 views
23

Jak zamienić literę o na literę e i z numerem o?Zamiana liter z wyrażeń regularnych

Po prostu próbowałem, ale nie sądzę, jest to dobry sposób robienia tego. Czy istnieje lepszy sposób?

my $str = 'Absolute force'; 
$str =~ s/e/___eee___/g; 
$str =~ s/o/e/g; 
$str =~ s/___eee___/o/g; 

wyjściowa: Abseluto ferco

Odpowiedz

25

Użyj transliteration operator: Np

$str =~ y/oe/eo/; 

$ echo "Absolute force" | perl -pe 'y/oe/eo/' 
Abseluto ferco 
+4

Ładne rozwiązanie! – klashxx

+1

Strona podręcznika, z którą się łączyłeś, nie zawiera w ogóle żadnych "informacyjnych" treści, ale zawiera link do tej bardziej przydatnej strony: http://perldoc.perl.org/perlop.html#Quote-and-Quote- like- Operatory – IQAndreas

2

z man sed:

r/źródło/docelowy/ Transliterate znaki w przestrzeni wzoru, które pojawiają się w źródle do odpowiedniego znaku w dest.

i komenda tr można to zrobić też:

$ echo "Absolute force" | tr 'oe' 'eo' 
Abseluto ferco 
+0

Ponieważ jest to pytanie [tag: perl], "perldoc perlre" (lub "man perlre") jest prawdopodobnie bardziej odpowiednie niż "man sed". – Bob

8

Jak już zostało powiedziane, sposobem na to jest transliteration operator

tr/SEARCHLIST/REPLACEMENTLIST/cdsr

y/SEARCHLIST/REPLACEMENTLIST/cdsr

Transliteruje wszystkie wystąpienia znaków znalezionych na liście wyszukiwania z odpowiednim znakiem na liście zastępczej. Zwraca liczbę znaków zastąpionych lub usuniętych. Jeśli łańcuch nie zostanie określony za pomocą operatora =~ lub !~, ciąg znaków $_ jest transliterowany.

Chciałbym jednak pochwalić Państwa twórczym wykorzystaniem wyrażeń regularnych. Twoje rozwiązanie działa, chociaż wystarczający byłby ciąg znaków zastępczy _ee_.

tr pomoże ci tylko w zastąpieniu znaków, więc chciałbym szybko nauczyć cię, jak używać wyrażeń regularnych do bardziej skomplikowanego zastępowania. Zasadniczo wystarczy użyć znacznika /e, aby wykonać kod w RHS. Poniższa zrobi wymianę ty dążyły do:

my $str = 'Absolute force'; 

$str =~ s/([eo])/$1 eq 'e' ? 'o' : 'e'/eg; 

print $str; 

Wyjścia:

Abseluto ferco 

Uwaga jak LHS (lewa strona) pasuje zarówno o i e i nimi RHS (prawą rękę side) robi test, aby zobaczyć, który pasuje i zwraca przeciwną do wymiany.

Teraz często mamy listę słów, które chcesz zastąpić, więc wygodnie jest po prostu zbudować skrót wartości od/do, a następnie dynamicznie budować wyrażenie regularne.Dodaje się robi:

my $str = 'Hello, foo. How about baz? Never forget bar.'; 

my %words = (
    foo => 'bar', 
    bar => 'baz', 
    baz => 'foo', 
); 
my $wordlist_re = '(?:' . join('|', map quotemeta, keys %words) . ')'; 

$str =~ s/\b($wordlist_re)\b/$words{$1}/eg; 

Wyjścia:

Hello, bar. How about foo? Never forget baz. 

Powyższa mogła już pracował dla e i o przypadku, jak dobrze, ale to już przesada. Zwróć uwagę, jak używać quotemeta, aby uciec od kluczy, na wypadek gdyby zawierały specjalny znak wyrażeń regularnych. Intuicyjnie użyłem też grupy niezapisującej wokół nich w $wordlist_re, aby zmienna mogła zostać dodana do dowolnego wyrażenia regularnego i zachowywać się zgodnie z oczekiwaniami. Następnie umieszczam grupę przechwytywania wewnątrz s///, ponieważ ważne jest, aby móc zobaczyć, co jest przechwytywane w regexie bez konieczności przechodzenia wstecz do wartości interpolowanej zmiennej.

2

Operator tr/// jest najlepszy. Jednakże, jeśli chcesz użyć operatora s/// (do obsługi więcej niż tylko zmiana pojedynczych liter), można napisać

$ echo 'Absolute force' | perl -pe 's/(e)|o/$1 ? "o" : "e"/eg' 
Abseluto ferco 

przechwytywanie nawiasach uniknąć niepotrzebnego $1 eq 'e' test w @ odpowiedź Millera.

Powiązane problemy