Объединить несколько регулярных выражений в одно

#php #regex #string

#php #регулярное выражение #строка

Вопрос:

Я пытаюсь написать код для переноса строки в латинские стихи. Есть несколько ограничений, о которых я позаботился, однако я не получаю желаемого результата. Мой код приведен ниже :

 <?php

$string = "impulerittantaenanimis caelestibusirae";

$precedingC = precedingConsonant($string);
$xrule = xRule($precedingC);
$consonantc = consonantCT($xrule);
$consonantp = consonantPT($consonantc);
$cbv = CbetweenVowels($consonantp);
$tv = twoVowels($cbv);

echo $tv;

function twoVowels($string)
{
    return preg_replace('/([aeiou])([aeiou])/', '$1-$2', $string);
}
function CbetweenVowels($string)
{
    return preg_replace('/([aeiou])([^aeiou])([aeiou])/', '$1-$2$3', $string);
}
function consonantPT($string)
{
    return preg_replace('/([^aeiou]p)(t[aeiou])/', '$1-$2', $string);
}
function consonantCT($string)
{
    return preg_replace('/([^aeiou]c)(t[aeiou])/', '$1-$2', $string);
}
function precedingConsonant($string)
{
    $arr1 = str_split($string);
    $length = count($arr1);
    for($j=0;$j<$length;$j  )
    {
        if(isVowel($arr1[$j]) amp;amp; !isVowel($arr1[$j 1]) amp;amp; !isVowel($arr1[$j 2]) amp;amp; isVowel($arr1[$j 3]))
        {
            $pc  ;  
        }
    }

    function strAppend2($string)
    {
        $arr1 = str_split($string);
        $length = count($arr1);


        for($i=0;$i<$length;$i  )
        {
            $check = $arr1[$i 1].$arr1[$i 2];
            $check2 = $arr1[$i 1].$arr1[$i 2].$arr1[$i 3];
            if($check=='br' || $check=='cr' || $check=='dr' || $check=='fr' || $check=='gr' || $check=='pr' || $check=='tr' || $check=='bl' || $check=='cl' || $check=='fl' || $check=='gl' || $check=='pl' || $check=='ch' || $check=='ph' || $check=='th' || $check=='qu' || $check2=='phl' || $check2=='phr')
            {
                if(isVowel($arr1[$i]) amp;amp; !isVowel($arr1[$i 1]) amp;amp; !isVowel($arr1[$i 2]) amp;amp; isVowel($arr1[$i 3]))
                {
                    $updatedString = substr_replace($string, "-", $i 1, 0);
                    return $updatedString;
                }
            }
            else
            {
                if(isVowel($arr1[$i]) amp;amp; !isVowel($arr1[$i 1]) amp;amp; !isVowel($arr1[$i 2]) amp;amp; isVowel($arr1[$i 3]))
                {
                    $updatedString = substr_replace($string, "-", $i 2, 0);
                    return $updatedString;
                }
            }
        }
    }
    $st1 = $string;
    for($k=0;$k<$pc;$k  )
    {
        $st1 = strAppend2($st1);
    }

    return $st1;
}
function xRule($string)
{
    return preg_replace('/([aeiou]x)([aeiou])/', '$1-$2', $string);
}
function isVowel($ch)
{
    if($ch=='a' || $ch=='e' || $ch=='i' || $ch=='o' || $ch=='u')
    {
        return true;
    }
    else
    {
        return false;
    }
}
function isConsonant($ch)
{
    if($ch=='a' || $ch=='e' || $ch=='i' || $ch=='o' || $ch=='u')
    {
        return false;
    }
    else
    {
        return true;
    }
}

?>
  

Я считаю, что если я объединю все эти функции, это приведет к желаемому результату. Однако я укажу свои ограничения ниже :

 Rule 1 : When two or more consonants are between vowels, the first consonant is joined to the preceding vowel; for example - rec-tor, trac-tor, ac-tor, delec-tus, dic-tator, defec-tus, vic-tima, Oc-tober, fac-tum, pac-tus, 

Rule 2 : 'x' is joined to the preceding vowel; as, rex-i. 

However we give a special exception to the following consonants - br, cr, dr, fr, gr, pr, tr; bl, cl, fl, gl, pl, phl, phr, ch, ph, th, qu. These consonants are taken care by adding them to the later vowel for example - con- sola-trix
n- sola-trix. 

Rule 3 : When 'ct' follows a consonant, that consonant and 'c' are both joined to the first vowel for example - sanc-tus and junc-tum

Similarly for 'pt' we apply the same rule for example - scalp-tum, serp-tum, Redemp-tor. 

Rule 4 : A single consonant between two vowels is joined to the following vowel for example - ma-ter, pa-ter AND Z is joined to the following vowel. 

Rule 5 : When two vowels come together they are divided, if they be not a diphthong; as au-re-us. Diaphthongs are - "ae","oe","au"
  

Комментарии:

1. Вы уверены, что Цицерон согласился бы с этим?

2. Прежде чем думать об объединении нескольких регулярных выражений или функций, вы должны сначала определить, выполняет ли каждая функция то, что она должна делать. Например, функция twoVowels не учитывает дифтонгов.

3. Что strAppend2 предполагается делать? Вы должны прокомментировать свой код и добавить краткое описание для каждой из ваших функций (поиск в PHPDoc).

Ответ №1:

Если вы внимательно посмотрите на каждое правило, вы увидите, что все они включают гласную в начале или предшествующую гласную. Как только вы это поймете, вы можете попытаться создать единый шаблон, введя [aeiou] фактор в начале:

 $pattern = '~
    (?<=[aeiou]) # each rule involves a vowel at the beginning (also called a
                 # "preceding vowel")
    (?:
        # Rule 2: capture particular cases
        ( (?:[bcdfgpt]r | [bcfgp] l | ph [lr] | [cpt] h | qu ) [aeiou] x )
      |
        [bcdfghlmnp-tx]
        (?:
            # Rule 3: When "ct" follows a consonant, that consonant and "c" are both
            # joined to the first vowel
            [cp] K (?=t)
          |
            # Rule 1: When two or more consonants are between vowels, the first
            # consonant is joined to the preceding vowel
            K (?= [bcdfghlmnp-tx]  [aeiou] )
        )   
      |
        # Rule 4: a single consonant between two vowels is joined to the following
        # vowel
        (?:
            K (?= [bcdfghlmnp-t] [aeiou] )
          | 
            # Rule 2: "x" is joined to the preceding vowel
            x K (?= [a-z] | (*SKIP)(*F) ) 
        )
      |
        # Rule 5: When two vowels come together they are divided, if they not be a
        # diphthong ("ae", "oe", "au")
        K (?= [aeiou] (?<! a[eu] | oe ) )
    )
~xi';
  

Этот шаблон предназначен для сопоставления только с позицией, в которой нужно поставить дефис (за исключением особых случаев правила 2), поэтому он использует много K , чтобы начать результат сопоставления с этой позиции, и просматривает, чтобы проверить, что следует без совпадающих символов.

 $string = <<<EOD
Aeneadum genetrix, hominum diuomque uoluptas,
alma Uenus, caeli subter labentia signa
quae mare nauigerum, quae terras frugiferentis
concelebras, per te quoniam genus omne animantum
EOD;

$result = preg_replace($pattern, '-$1', $string);
  

Ae-ne-a-dum ge-ne-trix, ho-mi-num di-u-om-qu-e u-o-lup-tas,
al-ma U-e-nus, cae-li sub-ter la-ben-ti-a sig-na
qu-ae ma-re nau-i-ge-rum, qu-ae ter-ras fru-gi-fe-ren-tis
con-ce-leb-ras, per te qu-o-ni-am ge-nus om-ne a-ni-man-tum

Обратите внимание, что я не включил несколько букв, таких как k, y и z, которых нет в латинском алфавите, не стесняйтесь включать их, если вам нужно обработать переведенные греческие слова или другие.