2014-04-17 16 views
23

Come posso scambiare la lettera o con la lettera e e e con o?Scambiare lettere con espressione regolare

Ho appena provato questo, ma non penso che questo sia un buon modo per farlo. C'è un modo migliore?

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

uscita: Abseluto ferco

risposta

25

Utilizzare la transliteration operator:

$str =~ y/oe/eo/; 

Ad es

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

Bella soluzione! – klashxx

+1

La pagina di manuale che hai collegato non contiene alcun contenuto "informativo", ma si collega a questa pagina più utile: http://perldoc.perl.org/perlop.html#Quote-and-Quote-like- Operatori – IQAndreas

2

da man sed:

y/sorgente/destinazione/ trascrivere i caratteri nello spazio modello che compaiono nella sorgente al carattere corrispondente dest.

e tr comando può fare anche questo:

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

Poiché questa è una domanda [tag: perl], 'perldoc perlre' (o' man perlre') è probabilmente più appropriato di 'man sed'. – Bob

8

Come già si è detto, il modo per farlo è il transliteration operator

tr/SEARCHLIST/REPLACEMENTLIST/cdsr

y/SEARCHLIST/REPLACEMENTLIST/cdsr

Trasloca tutte le occorrenze dei caratteri trovati nell'elenco di ricerca con il carattere corrispondente nell'elenco di sostituzione. Restituisce il numero di caratteri sostituiti o cancellati. Se non viene specificata alcuna stringa tramite l'operatore =~ o !~, la stringa $_ viene traslitterata.

Tuttavia, voglio elogiare l'uso creativo delle espressioni regolari. La soluzione funziona, anche se la stringa segnaposto _ee_ sarebbe stata sufficiente.

tr solo per aiutarvi a sostituire i personaggi, quindi mi piacerebbe insegnarvi rapidamente come utilizzare le espressioni regolari per una sostituzione di massa più complicata. Fondamentalmente, si usa semplicemente il tag /e per eseguire il codice nel RHS. Di seguito sarà anche fare la sostituzione si stava puntando:

my $str = 'Absolute force'; 

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

print $str; 

Uscite:

Abseluto ferco 

Si noti come il LHS (sinistra) corrisponde sia o e e, e RHS (mano destra lato) fa un test per vedere quale abbinato e restituisce il contrario per la sostituzione.

Ora, è normale avere un elenco di parole che si desidera sostituire, quindi è conveniente semplicemente creare un hash dei valori da/a e quindi creare dinamicamente l'espressione regolare.Di seguito lo fa:

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; 

Uscite:

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

Questo sopra potrebbe aver lavorato per il vostro caso e e o, come pure, ma Sarebbe stato eccessivo. Nota come io uso quotemeta per evitare le chiavi nel caso in cui contenessero un carattere speciale di espressione regolare. Ho anche utilizzato intenzionalmente un gruppo non di cattura attorno a loro in $wordlist_re in modo che la variabile potesse essere rilasciata in qualsiasi espressione regolare e comportarsi come desiderato. Quindi inserisco il gruppo di cattura all'interno di s/// perché è importante essere in grado di vedere ciò che viene catturato in un'espressione regolare senza dover tornare indietro al valore di una variabile interpolata.

2

L'operatore tr/// è il migliore. Tuttavia, se si voleva utilizzare l'operatore s/// (per gestire più di un semplice singole sostituzioni di lettere), si potrebbe scrivere

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

Le parentesi cattura evitare la $1 eq 'e' prova ridondante @ risposta di Miller.

Problemi correlati