How to make this regex?

Asked

Viewed 331 times

7

I have some difficulties using REGEX, so I would like help to separate the following text, example:

1ª Temporada - Nome da temporada
01 - Nome do ep um
02 - Nome do ep dois
03 - Nome do ep três
...
2ª Temporada - Nome da temporada
01 - Nome do ep um
02 - Nome do ep dois
03 - Nome do ep três
...

I need to make a explode and create an array called episodios and within this other arrays, each array corresponding to a season, in practice would be:

$episodios = array();
$episodios[1] = array(
    1 => Nome do ep um
    2 => Nome do ep dois
    3 => Nome do ep três
);
$episodios[2] = array(
    1 => Nome do ep um
    2 => Nome do ep dois
    3 => Nome do ep três
);

The first key in $episodios indicates the season, and the season keys indicate the episode number. How can I do this separation?

Below is an example of the original text that I must separate:

1ª Temporada – Shinigami Daikou
001. O Dia em que me Tornei Shinigami
002. Um Trabalho de Shinigami
003. O Desejo do Irmão mais Velho, o Desejo da Irmã mais Nova
004. Periquito Amaldiçoado
2ª Temporada – Invasão a Soul Society
026. Formação! A Pior Companhia
027. Libere o Golpe Final!
028. Orihime está sendo Visada
3ª Temporada – Fuga da Soul Society
052. Renji, Juramento da Alma! Luta Mortal com Byakuya
053. A Tentação de Ichimaru Gin, Resolução da Destruição
054. Um Juramento Realizado! Pegue Rukia Devolta
  • How does this text come to you? Through an input? Or is it a . txt file?

  • @Andreicoelho is a txt file, which I read and step to a variable all text

  • The text comes with these 3 ... even?

  • 1

    @dvd o .... is to say that may have more episodes, and not only 3

  • 1

    Just for the record, Leo, I wasn’t even going to talk, but since you may not have noticed, if your text is cluttered, the scripts of the other answers will fail, whereas the script I made in my reply, even if the text comes in various order, still he manages to take the exact number based on the string of each line https://answall.com/a/290031/3635 - I recommend you change the order of the episodes in each season and test all answers again, will notice the difference in behavior.

3 answers

8


Even with regex you will need to loop, regex alone won’t be able, for example:

<?php

$filmes = array();

$str = '1ª Temporada – Shinigami Daikou
001. O Dia em que me Tornei Shinigami
002. Um Trabalho de Shinigami
003. O Desejo do Irmão mais Velho, o Desejo da Irmã mais Nova
004. Periquito Amaldiçoado
2ª Temporada – Invasão a Soul Society
026. Formação! A Pior Companhia
027. Libere o Golpe Final!
028. Orihime está sendo Visada
3ª Temporada – Fuga da Soul Society
052. Renji, Juramento da Alma! Luta Mortal com Byakuya
053. A Tentação de Ichimaru Gin, Resolução da Destruição
054. Um Juramento Realizado! Pegue Rukia Devolta';

$linhas = preg_split('#[\r\n]+#', $str);

$ultima_temporada = 0;

foreach ($linhas as $value) {

    //Extrai o numero da temporada
    if (preg_match('#(\d+)ª[^a-z]+?temporada#i', $value, $temporada)) {

        $ultima_temporada = intval($temporada[1]);
        $filmes[$ultima_temporada] = array();

    //Extrai o nome e numero do episodio
    } elseif (preg_match('#(\d+)[^a-z]+([a-z].*?)$#i', $value, $episodio)) {

        $filmes[$ultima_temporada][ intval($episodio[1]) ] = $episodio[2];

    }
}

//Exibe
print_r($filmes);

The variable $ultima_temporada contains the last season found, and in the next loop if you find an episode it will be in the array that will receive the episodes, if the next line is a season then it will update the variable so that only the next season will receive the values and so on.

Already the intval($episodio[1]) converts the episode number value to integer (not to have zero ahead)

Example in IDEONE. Exit:

Array
(
    [1] => Array
        (
            [1] => Nome do ep um
            [2] => Nome do ep dois
            [3] => Nome do ep três
        )

    [2] => Array
        (
            [1] => Nome do ep um
            [2] => Nome do ep dois
            [3] => Nome do ep três
        )

)

Regex

Explaining the regex that extracts the seasons:

(\d+)ª[^a-z]+?temporada

 ^    ^
 .    .
 .    .
 .    .
 .    .
 .    . 
 .    .... verifica se existe algum separador entre temporada
 .
 .... Pega o numero da temporada

Explaining the regex that extracts the episodes:

(\d+)[^a-z]+([a-z].*?)$

 ^    ^       ^       ^
 .    .       .       .
 .    .       .       ... Para ir até o final da string
 .    .       .
 .    .       ..... Para pegar qualquer coisa, no caso o nome do episódio
 .    . 
 .    .... Identifica se existe um separador, ou seja o espaço é opcional
 .
 .... Pega o numero do episódio
  • 1

    I liked the explanation! Very good!

  • Thanks for the explanation, but I had to remove that part s? [-] in the first IF, because in my page it was not working with the real text I have

  • @Leoletto send me this text please

  • @Guilhermenascimento just added the question, a piece of the original text

  • 1

    @Leoletto that is not a hyphen, or is different from this -, I will adjust the regex - ps: the names of the episodes are also not related to the example, the tabs are very different.

  • Yes, I used the simplest as an example because I would like to have just the basis to make a gender separation, and looking at your example even if different, I managed to adjust for my real use :) thanks even for the explanation!

  • 1

    @Leoletto changed the regex to work independently of these problems, see the edition. IDEONE: https://ideone.com/FHiOSg

Show 2 more comments

7

I did without REGEX because I find it easier.

$text =    "1ª Temporada - Nome da temporada
            01 - Nome do ep um
            02 - Nome do ep dois
            03 - Nome do ep três
            2ª Temporada - Nome da temporada
            01 - Nome do ep um
            02 - Nome do ep dois
            03 - Nome do ep três
            ";

$texto = explode("\n", $text);
$episodios = array();
$y = -1;
for( $x = 0; $x < count($texto); $x++){
    if(stristr($texto[$x], 'Temporada')){
        $y++;
        $episodios[$y] = array();
    } else {
        $episodios[$y][] = trim($texto[$x]);
    }
}
print_r($episodios);

Another option would be to do so:

$text = fopen("text.txt", "r"); // seu arquivo que contém o texto
$episodios = array();
$y = -1;
while(!feof($text)){
    $linha = fgets($text, 1024);
    if(stristr($linha, 'Temporada')){
        $y++;
        $episodios[$y] = array();
    } else {
        $episodios[$y][] = trim($linha);
    }
}

print_r($episodios);

  • that <br /> could be exchanged for " n",

  • @Guilhermenascimento yes... I wasn’t sure. I’ll change.

  • 1

    another suggestion, change this $episodios[$y][] = $texto[$x]; for this reason $episodios[$y][] = trim($texto[$x]); and this $episodios[$y][] = $linha; for this reason $episodios[$y][] = trim($linha);

  • @Guilhermenascimento.

2

You can use this regex as well:

$pattern = "/[\d].*/";

It will take each line starting with a number creating an array in the index [0] of capture:

inserir a descrição da imagem aqui

Then you can mount the array with preg_match_all and foreach (similar to the while of the other answer):

$texto = '
1ª Temporada - Nome da temporada
01 - Nome do ep um
02 - Nome do ep dois
03 - Nome do ep três
2ª Temporada - Nome da temporada
01 - Nome do ep um
02 - Nome do ep dois
03 - Nome do ep três
';

$pattern = "/[\d].*/";
$resultado = preg_match_all($pattern, $texto, $matches);

$episodios = array();

$x = 1;
foreach($matches[0] as $items){
   if(stristr($items, 'Temporada')){
      $episodios[$x] = array();
      $x++;
   }else{
      $episodios[$x-1][] = $items;
   }
}

print_r($episodios);

Check it out at Ideone

Browser other questions tagged

You are not signed in. Login or sign up in order to post.