我必须处理植物的拉丁文名称,并需要在来自DB的植物名称的部分字的样式.这些名称以原始文本的形式存储.

示例字符串:Androsace angrenica 'Angelica' subsp. Violaceae

预期成绩:<em>Androsace angrenica</em> 'Angelica' subsp. <em>Violaceae</em>

一些特定的单词将被排除在斜体标签中,如上面的例子和数组$toFind中所示.

到目前为止,我得到了每个单词,但数组中的一个单词被<em></em>包住了,其他单词除外,如下所示:

<em>Androsace</em> <em>angrenica</em> 'Angelica' subsp. <em>Violaceae</em>

我希望能够防止像名称的第一部分那样跟随</em> <em>,并将它们加入到第一个示例中所示的单个标记环绕中.

# Array of words not be wraped in italic
$toFind = ["subsp.", "var.", "f.", "(voir)", "hybride"];

# Plant name
$name = "Androsace angrenica 'Angelica' subsp. Violaceae";

# Make an array of words from the name
$words = explode( " ", $name );

$newWords = [];

foreach( $words as $key => $word ) {
    if( in_array( $word, $toFind )) {
        $newWords[] =  $word;
    }else{
        # Catch the word or words surrounded  by single quotes like 'Angelica'
        $isHybrid = preg_match_all( "/'([^.]*?)'/", $word, $matches, PREG_PATTERN_ORDER );

        if( $isHybrid ){
            # No tags required
            $newWords[] = $word ;
        }else{
            # Tags required for these words
            $newWords[] = "<em> ". $word . "</em>";
        }
    }
}

echo implode(" ", $newWords);

请注意,此示例名称是许多可能的名称之一,如下所示:

  • Allium obliquum
  • Allium ostrowkianum (voir) A. oreophilum
  • Allium senescens subsp. glaucum
  • Allium sikkimense
  • Androsace × pedemontana

推荐答案

您的任务逻辑是字面和非字面单词排除的混合.事实是,您不需要将字符串explode()放入一个临时数组中,将每个单词与黑名单数组进行比较,然后使用正则表达式有条件地排除单引号括起来的单词,然后再次内爆可能发生Mutations 的单词.

更直接的做法是准备一个特定匹配前两个单词的正则表达式模式,然后使用否定的先行查找来取消后面的单词.那么preg_replace()是执行您的逻辑的最佳单调用工具.

代码:(Demo)

$blacklist = ["subsp.", "var.", "f.", "(voir)", "hybride"];
$prepped = array_map('preg_quote', $blacklist);             // escape special characters
$prepped[] = "'\S+'";                                       // do not escape special characters
$negLookAhead = '(?!' . implode('|', $prepped) . ')';       // create negated lookahead
$firstTwoWords = '(?:^\S+\s\S+)';                           // match the first two words of the string
$regex = '#' . $firstTwoWords . '|(?<=\s)' . $negLookAhead . '\S+(?=\s|$)#';

$names = [
    "Androsace angrenica 'Angelica' subsp. Violaceae",
    'Allium obliquum',
    'Allium ostrowkianum (voir) A. oreophilum',
    'Allium senescens subsp. glaucum',
    'Allium sikkimense',
    'Androsace × pedemontana',
];


// echo $regex;

var_export(
    preg_replace($regex, '<em>$0</em>', $names)  // works on an array or a string as input
);

输出:

array (
  0 => '<em>Androsace angrenica</em> \'Angelica\' subsp. <em>Violaceae</em>',
  1 => '<em>Allium obliquum</em>',
  2 => '<em>Allium ostrowkianum</em> (voir) <em>A.</em> <em>oreophilum</em>',
  3 => '<em>Allium senescens</em> subsp. <em>glaucum</em>',
  4 => '<em>Allium sikkimense</em>',
  5 => '<em>Androsace ×</em> <em>pedemontana</em>',
)

这不仅更直接、更简洁,而且如果您想要扩展文字或非文字排除,您不需要修改模式,只需要修改$preppedarray.

模式细分:

#              // start of pattern delimiter
(?:^\S+\s\S+)  // match two consecutive words if at start of string
|              // OR operator
(?<=\s)        // check that previous character was a whitespace
(?!            // do not allow match to qualify if any of the follow is satisfied
   subsp\.     // literal string match
   |           // OR operator
   var\.       // literal string match
   |           // OR operator
   f\.         // literal string match
   |           // OR operator
   \(voir\)    // literal string match
   |           // OR operator
   hybride     // literal string match
   |           // OR operator
   '\S+'       // single quote, one or more of any non-whitespace character, single quote
)              // close the negated lookahead logic
\S+            // match one or more non-whitespace characters
(?=\s|$)       // check that next character is a whitespace or the next position is the end of string
#              // end of pattern delimiter

Php相关问答推荐

WooCommerce拆分运输包裹上的商品数量增加运输成本

PHP-转义字符串内的双反斜杠

PHP-带POST验证的for循环

在Laravel中为表添加前缀,以将它们逻辑地分组

从订单项目中获取ACF WooCommerce产品价值

SendGrid响应PHP

有没有可能从composer 过时的输出中隐藏不需要的主要版本?

对表示大小的值后缀进行自定义排序(XXS、XS、S、M、L、XL、XXL)

更改WooCommerce checkout 中的错误消息以获得不可用的送货方式

使用 php Carbon 获取两个日期之间的随机日期和时间

当未 Select 任何变体时,在 WooCommerce 可变产品上显示自定义文本

多个产品类别 Select 自定义 WooCommerce 插件设置页面

如何在 PHP laravel 中将图像的透明背景转换为白色?

在 php 中生成 MAC ISO/IEC 9797-1

Woocommerce注册中的自定义复选框验证错误提示问题

如何获取用户之间的最新消息列表

PHP header() 是否缓存重定向,如果是,如何防止它这样做?

遇到特定键时修改二维数组以创建嵌套数据集

在全局安装 Composer 包后运行命令

WordPress 函数 get_post(post_id) 是否查询数据库?