Newsgroup: it.comp.os.linux.iniziare
Titolo: regex per riferimento

ho una stringa ab,cd,ef,gh ed avrei bisogno di dividerla in 4 con una
singola espressione regolare (da notare che i componenti possono
variare in numero da 1 a 1000)
per intercettarla basta [a-z]+(,[a-z]+)*
se voglio prelevarla nelle singole parti farei ([a-z]+(,([a-z]*))* ma
mi rintraccia solamente ab e gh (rispettivamente con \1 e \3) che è
l'ultimo rintracciabile.
invece vorrei che
\1 sia ab, \2 sia cd, \3 sia ef ecc (anche se non sono \1 \2 \3 \4 ma
\1 \3 \8 \9... l'importante è che ci sono tutti)
si può?
Matteo

Matteo Rossini wrote:

Scusa forse sono io che non capisco, ma perche' non puoi fare
([^,]+),([^,]+),([^,]+),([^,]+)

 \1 \3 \8 \9... l'importante � che ci sono tutti)
io proverei un approccio diverso
se la riga e' singola, per esempio, trasformerei la virgola in un "a 
capO" e quindi prenderei la riga che mi interessa
$ echo "ab,cd,ef,gh,xx,yy,zz" | sed 's/,/\n/g' | head -n 4 | tail -n1
gh
per avere il quarto elemento...
oppure potresti leggerla con un semplice read, usando come delimitatore 
(IFS) la virgola, e caricandola in un array
$ EXIFS=$IFS; IFS=","; echo ab,cd,ef,gh,xx,yy,zz | { read -a s; echo 
${s[3]}; }; IFS=$EXIFS
gh
-- 
Il Paradiso sono gli altri - Ertras

 singola espressione regolare ...
In pratica hai una lista separata da virgole e vuoi estrarre i singoli
campi. Una espressione regolare è lo strumento meno adatto.
man cut
man awk
man tr
Perchè non hai descritto il tuo problema invece della tua soluzione?
PS per errore ho inviato questa mia come una risposta privata. Mi scuso
con tutti i sottoscrittori e con Matteo.

Rispondo a tutti in un post.
La situazione è complessa
1 - il numero di elementi non è noto
2 - la stringa da matchare è inserita in un contesto più grande, per
esempio:
ciao*-pippo,pluto,paperino-*come va?*-bene,male-*ciao
prima rintraccio tutto quello che si trova tra *- e -*, (ma questo non
è un problema, l'ho già fatto), poi lancio l'espressione regolare che
mi dovrebbe restituire i tre elementi pippo pluto e paperino in \1 \2
\3 la prima volta e bene e male come \1 \2 la seconda volta.
3 - sono abbastanza abile ad utilizzare le combinazioni sed/cut/awk
(anche se quest'ultimo lo uso in modo molto basilare '{print $1}' e
poco più, ma gran parte delle volte basta), ma ho bisogno di una
singola espressione regolare e non mi trovo in shell ma in php, ma le
espressioni regolari sono le stesse tant'è vero che uso sed per
testarle; la complessità della situazione (quella sopradescritta è
ancora una esemplificazione) non mi consente di utilizzare altri
comandi specifici php (tipo quello per eplodere una stringa comma
separated in un array)
4 - è una sfida :-D
Matteo

Matteo Rossini wrote:

Beh no, le espressioni regolari di sed e di php sono parecchio differenti.
La domanda e': cosa ci devi fare con gli elementi estratti?

 Matteo
meglio se fai un esempio concreto di alcune righe di input, e di quello 
che vorresti in output
io cosi' come l'hai descritto non son riuscito ad afferrare bene


 La domanda e': cosa ci devi fare con gli elementi estratti?
ecco la situazione reale (risolta grazie all'equivalente di 'g' in
sed)
$a='{*testobase,"province, abbreviazioni",napoli,$unacitta$,milano*}';
questa stringa verrà privata di {* e *} e poi verranno fatte delle
translazioni:
$unacitta$ verrà preso da un array
$v=array( 'unacitta' => 'rm' );
"province, abbreviazioni" verrà lasciato così com'è
testobase napoli e milano verranno presi da
$t=array( 'testobase' => 'questo testo comprende %s e sono 1:%s 2:%s
3:%s', 'napoli' => 'na' );
visto che milano non esiste in questo array, allora non verrà
traslato.
si ottiene quindi
"questo testo comprende %s e sono 1:%s 2:%s 3:%s","province,
abbreviazioni","na","rm","milano"
il tutto viene passato in pasto a printf che lo traduce in
"questo testo comprende province, abbreviazioni e sono 1:na 2:rm
3:milano"
il ragionamento è contorto ma è funzionale
il codice:
$a='{*testobase,"province, abbreviazioni",napoli,$unacitta$,milano*}';
$v=array( 'unacitta' => 'rm' );
$t=array( 'testobase' => 'questo testo comprende %s e sono 1:%s 2:%s
3:%s', 'napoli' => 'na' );
$c=preg_match_all('/(((,|\*)(?<lang>[A-Za-z0-9_-]+))|("(?<text>[^"]
+)"))|((\$)(?<var>[A-Za-z_]+)\$)/',$a,$o);
$par=array();
for($i=0;$i<$c;$i++){
        if($o['lang'][$i])$par[$i]=(isset($t[$o['lang'][$i]]))?$t[$o
['lang'][$i]]:$o['lang'][$i];
        if($o['text'][$i])$par[$i]=$o['text'][$i];
        if($o['var'][$i])$par[$i]=$v[$o['var'][$i]];
}
$s=call_user_func_array('sprintf',$par);
echo $s;
l'espressione regolare viene esplosa in
Array
(
    [lang] => Array
        (
            [0] => testobase
            [1] =>
            [2] => napoli
            [3] =>
            [4] => milano
        )
    [text] => Array
        (
            [0] =>
            [1] => province, abbreviazioni
            [2] =>
            [3] =>
            [4] =>
        )
    [var] => Array
        (
            [0] =>
            [1] =>
            [2] =>
            [3] => unacitta
            [4] =>
        )
)
Matteo