2012-06-07 10 views
5

Per un parser di script personalizzato in PHP, vorrei sostituire alcune parole in una stringa multilinea che contiene virgolette doppie e singole. Tuttavia, solo il testo che è all'esterno di le virgolette può essere sostituito.Come sostituire le parole al di fuori delle virgolette doppie e singole

Many apples are falling from the trees.  
"There's another apple over there!"  
'Seedling apples are an example of "extreme heterozygotes".' 

Per esempio, vorrei sostituire 'mela' con 'pera', ma solo al di fuori delle frasi di citazione. Quindi in questo caso solo la "mela" all'interno di "Molte mele cadono dagli alberi" verrebbe presa di mira.

È possibile che questo avrebbe dato il seguente risultato:

Many pears are falling from the trees.  
"There's another apple over there!"  
'Seedling apples are an example of "extreme heterozygotes".' 

Come posso raggiungere questo obiettivo?

+0

Puoi pubblicare lo script di analisi di PHP in modo che possiamo suggerire le modifiche. –

risposta

6

Questa funzione fa il trucco:

function str_replace_outside_quotes($replace,$with,$string){ 
    $result = ""; 
    $outside = preg_split('/("[^"]*"|\'[^\']*\')/',$string,-1,PREG_SPLIT_DELIM_CAPTURE); 
    while ($outside) 
     $result .= str_replace($replace,$with,array_shift($outside)).array_shift($outside); 
    return $result; 
} 

Come funziona Si divide da stringhe tra virgolette, ma include queste stringhe tra virgolette, questo ti dà alternata non citato, citato, non citato, citato ecc stringhe in un array (alcune stringhe non citate potrebbero essere vuote). Quindi si alterna tra la sostituzione della parola e la non sostituzione, quindi vengono sostituite solo le stringhe non quotate.

Con il vostro esempio

$text = "Many apples are falling from the trees.  
     \"There's another apple over there!\"  
     'Seedling apples are an example of \"extreme heterozygotes\".'"; 
$replace = "apples"; 
$with = "pears"; 
echo str_replace_outside_quotes($replace,$with,$text); 

uscita

Many pears are falling from the trees.  
"There's another apple over there!"  
'Seedling apples are an example of "extreme heterozygotes".' 
+0

Funzionante bene, grazie mille! – Nick

+0

Non sono riuscito a ottenere la regex utilizzata nella mia [prima risposta] (http://stackoverflow.com/revisions/10929115/1) per funzionare in modo affidabile, quindi ho creato questa funzione che invece funziona sempre. – Timm

+0

Ho testato il tuo script e trovato un bug. Se hai i caratteri di escape \ 'o \ "nella tua stringa, si chiuderanno presto portando a risultati imprevedibili. Questo regex lo corregge/(' (?: [^ \\\\ '] + | \\\\ (\\ \\\\\\) *) * '| \ "(:? [^ \\\\\".] + | \\\\ (\\\\\\\\) *) * \ ") /. Non è carino ma funziona. Ci deve essere una soluzione più elegante ma non posso sprecare altro tempo su questo momento. –

0

Solo un pensiero: creare una stringa temporanea rimuovendo le parti citate, sostituire ciò che è necessario, quindi aggiungere le parti citate rimosse.

+0

Come si aggiungono nuovamente le parti citate alla stringa originale, nelle loro posizioni originali? – Nick

1

sono arrivato fino a questo:

function replaceOutsideDoubleQuotes($search, $replace, $string) { 
    $out = ''; 
    $a = explode('"', $string); 
    for ($i = 0; $i < count($a); $i++) { 
     if ($i % 2) $out .= $a[$i] . '"'; 
     else $out .= str_replace($search, $replace, $a[$i]) . '"'; 
    } 
    return substr($out, 0, -1); 
} 

La logica è: fai esplodere stringa tra virgolette, in modo che i dispari elementi del ritorno stringa-array rappresentano testo al di fuori citazioni, e anche quelli rappresenta il testo tra virgolette.

Quindi, è possibile creare l'output concatenando parti originali e parti sostituite in alternativa, ok?

esempio Lavorare qui: http://codepad.org/rsjvCE8s

+0

Grazie, ma funziona solo per le doppie virgolette ... Avrei bisogno di qualcosa che sostituisca solo le virgolette doppie E singole :) – Nick

0

È possibile utilizzare preg_replace, usando un'espressione regolare per sostituire le parole dentro ""

$search = array('/(?!".*)apple(?=.*")/i'); 
$replace = array('pear'); 
$string = '"There\'s another apple over there!" Seedling apples are an example of "extreme heterozygotes".'; 

$string = preg_replace($search, $replace, $string); 

è possibile aggiungere più oggetti possibili ricercabili aggiungendo un altro RegEx in $ search e un'altra stringa di sostituzione in $ replace

Questo RegEx utilizza un lookahead e lookbehind per scoprire se la stringa cercata è all'interno di ""

+0

Mi dispiace, ho appena notato che ho letto la domanda sbagliata - è stato chiesto il contrario. Lo cambierò ... – Katai

+0

Sembra fare l'opposto di ciò che la domanda chiede, sostituendo il testo ** dentro ** le virgolette e non all'esterno. –

Problemi correlati