【问题标题】:How to write pattern for get combined words with description from text?如何编写模式以从文本中获取组合单词和描述?
【发布时间】:2018-05-24 15:11:20
【问题描述】:

我有示例文本:

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

我有示例代码用于获取大写单词到数组键和数组值所有大写单词右边的文本:

$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 "</pre>";

结果执行代码:

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

但是我有第二种类型的文本有问题:

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

在这种类型的文本中,我有带有符号// 的单词。这种类型用一个描述来表达两个词。 (WORD//WORD 描述)。当我使用旧代码时,结果将是:

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

如何编写模式以获取示例结果:

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

这里为所有带有//符号的单词保存了一个描述。

【问题讨论】:

  • 您从未解释过您要做什么,请使用英文示例输入。
  • 请发布您的工作代码并附上ideone.com 的链接,以便有一个改进的起点。

标签: php regex utf-8


【解决方案1】:

一种使用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 =&gt; $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";
}

demo
variant

【讨论】:

  • 老我不在 php 中使用生成器。你能告诉我带有产量生成器的示例代码吗?我有大小为 13mb 的文件。我必须用它测试代码。如果可能的话,请向我展示在此任务中使用 yield 的示例。
  • @Otabek:我添加了一个示例。
猜你喜欢
  • 2016-10-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-20
  • 2011-06-07
  • 1970-01-01
相关资源
最近更新 更多