Autor Zpráva
_Martin_
Profil *
Ahoj, narazil jsem na zapeklitý úkol. Pomocí funkce explode rozsekávám string do pole, kde jednotlivé položky jsou odděleny mezerami. Příklad:

$string = "jedna dvě tři";
$pole = explode(" ", $string);
$pole[0] = "jedna";
$pole[1] = "dvě";
$pole[2] = "tři";


Potud v pohodě. Ale jak to vyřešit, když některá z položek pole má obsahovat mezery? Ve stringu bude v uvozovkách. Příklad:

$string = "jedna 'dvě a půl' tři";


Z tohoto je potřeba získat opět toto:

$pole[0] = "jedna";
$pole[1] = "dvě a půl";
$pole[2] = "tři";


Jak na to? Zkoušel jsem různé nahrazování pomocí preg_replace, ale spolehlivé řešení jsem nenašel, a to ani pomocí Googlu nebo PHP manuálu. Asi to bude pro vás kabrňáky dost triviální, jistě to jde vyřešit jedním řádkem kódu. Ale jak, strécu, jak? :-O
Jozin
Profil
Zdravím,

nevím, zda jsem pochopil problém správně, ale dalo by se to udělat takto:
<?php

$string = "jedna dvě tři";
$string = explode(" ", $string);
$string[1] = "'" . $string[1] . " a půl'";
$string = implode(" ", $string);
echo $string;

EDIT: zapomněl jsem na druhé rozsekání omlouvám se.
_Martin_
Profil *
To jsme se nepochopili, omlouvám se, možná jsem to špatně napsal.
Dejme tomu, že původní string je "jedna 'dvě a půl' tři". Jde o to, rozsekat ho do pole s tím, že oddělovačem je mezera (ale ne mezera mezi uvozovkami).
Tzn. je potřeba získat toto pole:

$pole[0] = "jedna";
$pole[1] = "dvě a půl";
$pole[2] = "tři";
__construct
Profil
_Martin:
Skús použiť regulár ~\b[ a-záäéëěíóöôúůüýčďňŕřšťžĺľ]+\b~.
_Martin_
Profil *
Určitě by šlo nějak nahradit v původním stringu všechny mezery mezi uvozovkami třeba za %_%. Tím pádem by se dal už string rozsekat klasicky pomocí explode podle mezer. A nakonec v jednotlivých částech pole nahradit všechny výskyty %_% za mezeru. Příklad:

Máme tento string:
$string = "jedna 'dvě a půl' tři";


Z něj nějak (jak?) uděláme toto:
$string = "jedna 'dvě%_%a%_%půl' tři";


Pak už není problém udělat explode(" ",$string); a máme požadované kousky:

$pole[0] = "jedna";
$pole[1] = "dvě%_%a%_%půl";
$pole[2] = "tři";


V nich už se lehce pomocí str_replace nahradí %_% za mezery. Ale jak udělat to nahrazení mezer v původním stringu jen mezi uvozovkami?
_Martin_
Profil *
__construct:
Díky za nápad, ale to je strašně nesystémové. Co když v tom stringu budou jiné znaky? Otazníky, závorky, polské znaky, atd... nebude to fungovat. Jde o to, že v těch uvozovkách může být cokoliv kromě uvozovek. Vše mezi uvozovkami pak musí být hodnota té položky v poli.
__construct
Profil
_Martin:
Pokiaľ chceš zachytiť všetko okrem apostrofov regulár sa Ti zmrskne na ~[^']+~.
Sir Tom
Profil
_Martin_:
Možná budu plácat, ale napadlo mě:
1. Rozdělit $string na pole, kde oddělovačem bude znak uvozovky.
2. Nyní procházet všechny prvky v poli a prvek, který bude končit nebo začínat mezerou (v původním stringu je tato mezera před nebo za uvozovkou), ještě rozdělit do jiného pole s oddělovačem mezery.
3. Poskládat prvky v polích (asi opět do komplet nového pole, nebo podle původního stringu) tak, aby šli za sebou.
Mike8748
Profil
$string = "jedna 'dvě a půl' tři";
$p=str_getcsv($string,' ','\'');
var_dump($p);


edit: funkce str_getcsv je dostupná od php 5.3, v manuálu jsou uvedené "náhrady" pro starší verzi
_Martin_
Profil *
Sir Tom, Mike8748:
Díky, to druhé řešení vypadá líp, ale škoda toho omezení na PHP 5.3+, to je dost limitující... v komentářích v PHP manuálu jsou nějaké náhražky, ale je to zase strašně krkolomné.
_Martin_
Profil *
Asi zůstanu u nahrazení mezer v textu mezi uvozovkami a následném doplnění zpět. Bude to nejjednodušší, spolehlivé a čitelné.

Jak z tohoto stringu:
$string = "jedna 'dvě a půl' tři";


Udělat toto?
$string = "jedna 'dvě%_%a%_%půl' tři";
Tori
Profil
preg_replace("/'(.+?)'/e", "str_replace(' ', '%_%', '\\1')", $string);
_Martin_
Profil *
Tori:
Díky moc za tip s možností vložení str_replace do preg_replace. Velice elegantní a bezvadně funkční.
Vyřešeno.

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm:

0