Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

IagoBorges

[PHP] preg_match_allEu estou tendo que estudar php e estou travado nes

Recommended Posts

Eu estou tendo que estudar php e estou travado nessa função. Eu entendi o que ela faz, a sintaxe, tudo direitinho. O que eu não entendi é como que ela armazena os 'casamentos' na array usando PREG_PATTERN_ORDER. Na verdade, na teoria eu entendi, só não consigo aplicar.

 

Por exemplo:

preg_match_all('|([0-9]{2})\/([0-9]{2})\/([0-9]{4})|U','27/09/2012',$match);

 

O resultado teria que ser mais ou menos assim:

$match[0] = 27/09/2012

$match[1] = 27

$match[2] = 09

$match[3] = 2012

 

E realmente, quando uso print_r, é isso que retorna. Mas o problema é que não consigo, por exemplo, usar um echo pra mostrar o 27($match[1]), nem pra mostrar o 09($match[2]). Eu consigo fazer isso usando PREG_SET_ORDER, mas não com PREG_PATTERN_ORDER. Alguém poderia me mostrar como fazer o echo ?

Compartilhar este post


Link para o post
Compartilhar em outros sites

PREG_PATTERN_ORDER descreve o comportamento padrão de preg_match() e preg_match_all(), logo, pode omiti-lo.

 

Por padrão isso faz com que no índice zero contenha tudo aquilo que a ER casou, de forma completa, e nos outros índices tudo aquilo que cada grupo, se presentes na ER, casaram, individualmente.

 

PREG_SET_ORDER é um bicho muito doido, e muitas vezes complicado de se explicar e entender (o manual tem boa parte da culpa), que produz tantos grupos de arrays quantos casamentos completos a ER produziu:

 

Clarificando o que diz no manual, sobre preg_match():

 

<?php
preg_match_all(

   "|<[^>]+>(.*)</[^>]+>|U",

   "<b>example: </b><div align=\"left\">this is a test</div>",

   $out, PREG_SET_ORDER
);

Isso produz, em $out:

 

array
 0 => 
   array
     0 => string '<b>example: </b>' (length=16)
     1 => string 'example: ' (length=9)
 1 => 
   array
     0 => string '<div align="left">this is a test</div>' (length=38)
     1 => string 'this is a test' (length=14)

Essa ER casa uma tag HTML com abertura e fechamentos idênticos mas sem atributos (<b>, <i>, <em>, <strong> e etc.)

 

Na string de entrada temos duas tags, <b> e <div>. E dentro delas, algum valor.

 

O objetivo da flag é simplificar tanto a leitura quanto a manipulação dos dados.

 

Sem ela sabe-se que teremos, como comportamento padrão, no índice zero de $out todos os casamentos completos e no índice um (já que temos só um grupo), todos os valores casados pelo grupo.

 

PREG_SET_ORDER agrupa as informações, fazendo com que no índice zero-zero resida o texto completo casado e no zero-um o texto casado pelo grupo. E ponto.

 

Se o padrão casar mais uma vez, no índice um-zero teremos o texto completo casado e no um-um, aquilo que o grupo casou.

 

Casou uma terceira vez? dois-zero o texto completo e no dois-um seu valor.

 

E por aí vai.

 

Trocando em miúdos, o que você faria para representar o primeiro casamento:

 

echo $out[ 0 ][ 0 ], ' casou ', $out[ 1 ][ 0 ];

Com PREG_SET_ORDER você faria:

 

echo $out[ 0 ][ 0 ], ' casou ', $out[ 0 ][ 1 ];

Fica mais conciso de se ler e de se interpretar. Mas só vale para quando uma mesma ER vai casar muitas vezes o mesmo padrão na mesma string.

Compartilhar este post


Link para o post
Compartilhar em outros sites

IagoBorges, primeiro vamos ver para que serve a função preg_match_all.

 

Essa função retorna todas as ocorrências do pattern com o texto. Como podemos ver no nome da função, o 'all' sugere que a função tenta casar o maior número possível do pattern.

 

Visto que um grupo do pattern (grupo = parênteses) pode ter N ocorrências num texto, então, cada casamento do pattern será retornado num array multimensional.

 

 

Vamos exemplificar com base no código que você enviou, assim fica mais fácil entender

 

//note que nosso texto tem duas datas

$texto = '27/09/2012 - 28/09/2012';

 

//vamos usar o preg_match_all

preg_match_all('/([0-9]{2})\/([0-9]{2})\/([0-9]{4})/', $texto, $match);

 

 

var_dump($match);

 

 

A saída de var_dump será a seguinte:

 

array(4) {

[0]=>

array(2) {

[0]=>

string(10) "27/09/2012"

[1]=>

string(10) "28/09/2012"

}

[1]=>

array(2) {

[0]=>

string(2) "27"

[1]=>

string(2) "28"

}

[2]=>

array(2) {

[0]=>

string(2) "09"

[1]=>

string(2) "09"

}

[3]=>

array(2) {

[0]=>

string(4) "2012"

[1]=>

string(4) "2012"

}

}

 

 

 

//Indice[0] = texto casado (se não quiser que seja retornado esse índice, use o flag PREG_SET_ORDER)

 

//Indice[1] = texto do casamento do primeiro grupo do pattern - ([0-9]{2})

Note aqui o array multimensional que a função preg_match_all retorna para cada grupo do pattern.

 

então o casamento do nosso primeiro grupo está no índice [1]

indice[1][0] = 27 - teve a primeira ocorrência - '27/09/2012 - 28/09/2012'

indice[1][1] = 28 - teve a segunda ocorrência - '27/09/2012 - 28/09/2012'

 

 

e segue essa mesma idéia para os outros índices.

 

 

//obtendo os valores:

 

//dia

$dia1 = $match[1][0] // 27

$dia2 = $match[1][1] // 28

 

//mes

$mes1 = $match[2][0] // 09

$mes2 = $match[2][1] // 09

 

//mes

$ano1 = $match[3][0] // 2012

$ano2 = $match[3][1] // 2012

---------

 

 

Você notou o objetivo da função preg_match_all?

 

 

 

 

Agora vamos voltar à sua dúvida

 

 

Você quer obter o casamento numa única data, ou seja, não haverá duas ou mais datas juntas ao texto, correto?

 

Neste caso, o mais apropriado é usar preg_match (sem o _all). Além de ser mais apropriado, essa função retorna uma array simples o que torna mais fácil trabalhar.

 

//alterando seu código para usar preg_match ao invés de preg_match_all

preg_match('|([0-9]{2})\/([0-9]{2})\/([0-9]{4})|U','27/09/2012',$match);

 

 

//Obtendo os valores

$dia = $match[1];

$mes = $match[2];

$ano = $match[3];

 

echo $dia . '/' . $mes . '/' . $ano;

 

 

 

Espero ter ajudado.

 

 

Lembrando que foquei na sua dúvida quanto à função preg_match, se sua pattern está bem escrita, não entrei em detalhes.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Toda vez que eu tento dar echo em algum elemento da array $match pra ver como funciona, ele retorna um erro:

 

Notice: Array to string conversion in C:\xampp\htdocs\new.php on line 8.

 

O que estou fazendo é:

 

$dia = $match[1];
echo $dia;

 

Quando uso isso também da a mesma coisa:

 

foreach($match as $valor){
echo $valor . ' ';
}

 

Resolvi isso. É que o valor de $match[1] é um array, que não pode simplesmente ser exibido. Tem que ser $match[1][0].

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.