regex replace - podmíněné nahrazení rubrika: Programování: PHP

13 rmaslo
položil/-a 8.1. 19:32
 
upravil/-a 11.1. 2:32

Mějme text v kterém jsou nějakými oddělovači určeny 4 skupiny. Pokud se první skupina rovná druhé tak bych chtěl vypsat třetí skupinu, pokud jsou různé tak čtvrtou skupinu. To celé v tom textu může být samozřejmě vícekrát.

Například z:

'fdlkg jfdklgj fdkl <<xxx==xxx??aaa%%bbb>> gjfkl jgfdlkgj <<xxx==yy??ddd%%eee>> fdsklgj fdsklgj fdklgjf'

bych chtěl ziskat

'fdlkg jfdklgj fdkl aaa gjfkl jgfdlkgj eee fdsklgj fdsklgj fdklgjf'

Jsem to schopen napsat pomocí preg_replace_callback

$s = 'fdlkg jfdklgj fdkl <<xxx==xxx??aaa%%bbb>> gjfkl jgfdlkgj <<xxx==yy??ddd%%eee>> fdsklgj fdsklgj fdklgjf';
$s = preg_replace_callback('/\\<\\<(.*)\\=\\=(.*)\\?\\?(.*)\\%\\%(.*)\\>\\>/U', function ($matches) {
return ($matches[1]===$matches[2]?$matches[3]:$matches[4]); }, $s);
echo $s;

Ale něco mi našeptává, že by to mělo jít i jen pomocí preg_replace, akorát to asi neumím uchopit za ten správný konec.

Ty oddělovače ['<<', '==', '??', '%%', '>>'] si v principu můžu zvolit jiné, ale to asi jedno.

------------ Řešení

$re = '/\<\<(.*)\=\=(\1)\?\?(.*)\%\%(.*)\>\>|\<\<(.*)\=\=(.*)\?\?(.*)\%\%(.*)\>\>/U';
$str = 'fdlkg jfdklgj fdkl <<xxx==xxx??aaa%%bbb>> gjfkl jgfdlkgj <<xxx==yy??ddd%%eee>> fdsklgj fdsklgj fdklgjf';
$subst = '$3$8';
$result = preg_replace($re, $subst, $str);

Principiálně - jsou tam dva podobné výrazy oddělená | buď to sežere ten první nebo až ten druhý.
Každý načítá ty čtyři skupiny oddělené těmi oddělovači
V tom prvním je zabudováno, že ta druhá skupina musí být stejná jako ta první ... to je to \1
V případě, že se provede ten první tak dám do nahrazení tu třetí grupu (then) z té první části
V případě, že se provede ten druhý tak dám do nahrazení tu čtvrtou grupu (else) z té druhé části, tj. celkově osmou grupu

Online ukázka: https://regex101.com/r/nhAR6W/2

odkaz Vyřešeno
8 skliblatik
odpověděl/-a 10.1. 19:16

Teď to nevyzkouším, ale nešlo by něco takového? :

\<\<(.*(==)?){2}\?\?(.*)\%\%.*\>\> | \<\<(.*(==).*)\?\?.*\%\%(.*)\>\>

Tzn. když se to chytne na 1. část (před |) bude tam část za ??, když se chytne 2. (za |) část bude tam část za %%. Ale je to od boku, chce to testnout.

Komentáře

  • rmaslo : Jo, to je přesně ten směr kterým jsem potřeboval nakopnout! Já se to furt smažil udělat přes ty podmínky typu (?(1)yes|no) a furt mi nějak nejde. Tímhle se to obejde protože buď to ta první část (kde se to rovná) jednoduše sežere nebo zbude na tu druhou. Řešení dám přímo do zadání. Tady bych to nezformátoval. Dík moc. 11.1. 2:35

Pro zobrazení všech 3 odpovědí se prosím přihlaste:

Rychlé přihlášení přes sociální sítě:

Nebo se přihlaste jménem a heslem:

Zadejte prosím svou e-mailovou adresu.
Zadejte své heslo.