Как написать шаблон для получения комбинированных слов с описанием из текста? - PullRequest
0 голосов
/ 24 мая 2018

У меня есть образец текста:

$text = "
АДАБГОЊ љои адаб-
омўзї.
АДАБДОН ادبدان ошно бо адабу фарњанг.
тиллову нуќра бо мањак ва ѓ.; зар(р)и иёр тил-
лои холис.
АЁРА اياره 1. ёра, дастбиранљан.
";

И у меня есть пример кода для получения прописных слов в ключе массива и для значения массива всего текста справа от прописных слов:

<code>$regex = '~\b-(?:\R|\h)\b~u';
$text = preg_replace($regex, '', $text);
$pattern = '~^(\p{Lu}+)\h+(.*(?:\R(?!\p{Lu}+\h).*)*)~mu';
preg_match_all($pattern, $text, $matches);
$result = array_combine(array_map('mb_strtolower', $matches[1]), preg_replace('~\s*\R++\s*~u', ' ', preg_replace('~\p{Arabic}+~u', '', $matches[2])));
echo "<pre>";
print_r($result);
echo "
";

Результат exec code:

Array
(
    [адабгоњ] => љои адабомўзї. 
    [адабдон] =>  ошно бо адабу фарњанг. тиллову нуќра бо мањак ва ѓ.; зар(р)и иёр тиллои холис. 
    [аёра] =>  1. ёра, дастбиранљан. 
)

Но у меня есть текст второго типа, где у меня проблемы:

$text = "
АДАБГОЊ//АДАБГАЊ ادبگه//ادبگاه љои адаб-
омўзї.
АДАБДОН ادبدان ошно бо адабу фарњанг.
АЁЃ//АЁЌ т. اياق//اياغ кит. пиёла, ќадањ, соѓар.
АЁР//ИЁР а. ايار санљидани дараљаи холисияти
тиллову нуќра бо мањак ва ѓ.; зар(р)и иёр тил-
лои холис.
АЁРА اياره 1. ёра, дастбиранљан.
АДУ//АДУВ а. عدو ниг. адў.
";

В этом тексте типа у меня есть слова с символами //. Этот тип состоит из двух слов с одним описанием. (WORD // WORD description). Когда я использую мой старый код, результат будет:

Array
(
    [адабдон] =>  ошно бо адабу фарњанг. АЁЃ//АЁЌ т. // кит. пиёла, ќадањ, соѓар. АЁР//ИЁР а.  санљидани дараљаи холисияти тиллову нуќра бо мањак ва ѓ.; зар(р)и иёр тиллои холис. 
    [аёра] =>  1. ёра, дастбиранљан. АДУ//АДУВ а.  ниг. адў. 
)

Как написать шаблон для получения образца результата:

Array
(
    [адабдон] =>  ошно бо адабу фарњанг. 
    [аёѓ] => т. // кит. пиёла, ќадањ, соѓар. 
    [аёк] => т. // кит. пиёла, ќадањ, соѓар.
    [аёр] => а.  санљидани дараљаи холисияти тиллову нуќра бо мањак ва ѓ.; зар(р)и иёр тиллои холис. 
    [иёр] => а.  санљидани дараљаи холисияти тиллову нуќра бо мањак ва ѓ.; зар(р)и иёр тиллои холис. 
    [аёра] =>  1. ёра, дастбиранљан.
    [аду] =>  а.  ниг. адў. 
    [адув] =>  а.  ниг. адў. 
)

Здесь для всех слов с символом // сохранено одно описание.

1 Ответ

0 голосов
/ 24 мая 2018

Способ, который использует preg_split:

$text = "
АДАБГОЊ//АДАБГАЊ ادبگه//ادبگاه љои адаб-
омўзї.
АДАБДОН ادبدان ошно бо адабу фарњанг.
АЁЃ//АЁЌ т. اياق//اياغ кит. пиёла, ќадањ, соѓар.
АЁР//ИЁР а. ايار санљидани дараљаи холисияти
тиллову нуќра бо мањак ва ѓ.; зар(р)и иёр тил-
лои холис.
АЁРА اياره 1. ёра, дастбиранљан.
АДУ//АДУВ а. عدو ниг. адў.
";

$defs = preg_split('~^(\p{Lu}+(?://\p{Lu}+)*)\h+~mu', trim($text), -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);

$result = [];
while ( false !== $items = current($defs) ) {
    $def = trim(preg_replace('~(?:\s*\p{Arabic}+(?://\p{Arabic}+)*)?\s+~u', ' ', next($defs)));
    foreach (explode('//', $items) as $item) {
        $result[$item] = $def;
    }
    next($defs);
}

print_r($result);

demo


Предложение: если текст взят из очень большого файла и если выне нужно иметь весь массив в памяти, вы можете переписать этот код с помощью определяемого пользователем потокового фильтра и, в конечном итоге, генератора, который выдает ключи и значения (yield $key => $value;) для сохранения памяти, например:

class NormalizeFilter extends php_user_filter
{
    public function filter($in, $out, &$consumed, $closing)
    {
        while ($bucket = stream_bucket_make_writeable($in)) {
            $bucket->data = preg_replace('~\s+\p{Arabic}*(?://\p{Arabic}+)*\s*(?!^\p{Lu})~mu', ' ', $bucket->data);
            $consumed += $bucket->datalen;
            stream_bucket_append($out, $bucket);
        }
        return PSFS_PASS_ON;
    }
}

stream_filter_register("norm", "NormalizeFilter")
    or die("Failed to register filter");

function genDefs($fh, $bufferSize = 1024) {
    while ( false !== $line = fgets($fh, $bufferSize) ) {
        if ( preg_match('~^(\p{Lu}+(?://\p{Lu}+)*) \K.*\S~u', $line, $m) ) {
            foreach ( explode('//', $m[1]) as $item ) {
                yield $item => $m[0];
            }
        }
    }
}

$fh = fopen('php://filter/read=norm/resource=file:///path/to/file.txt', 'r');

$defs = genDefs($fh);

foreach ($defs as $item => $definition) {
    echo "$item: $definition\n";
}

демо
вариант

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...