PHP 中的正则表达式:获取字符串中第一个单词之后的所有单词,并将它们全部截断为第一个字符

问题描述 投票:0回答:4

我对正则表达式很糟糕。

我有一个字符串,里面可能有1个或多个单词(通常是2个或3个),通常是人名,例如:

$str1 = 'John Smith';
$str2 = 'John Doe';
$str3 = 'David X. Cohen';
$str4 = 'Kim Jong Un';
$str5 = 'Bob';

我想按如下方式转换每个:

$str1 = 'John S.';
$str2 = 'John D.';
$str3 = 'David X. C.';
$str4 = 'Kim J. U.';
$str5 = 'Bob';

我的猜测是我应该首先匹配第一个单词,如下所示:

preg_match( "^([\w\-]+)", $str1, $first_word )

然后是第一个单词之后的所有单词...但是我如何匹配这些单词呢?我应该再次使用 preg_match 并在参数中使用 offset = 1 吗?但该偏移量是以字符或字节为单位的,对吗?

无论如何,在我匹配第一个后面的单词之后,如果存在,我应该为每个单词做类似的事情:

$second_word = substr( $following_word, 1 ) . '. ';

或者我的做法完全错误?

谢谢

ps - 当字符串包含三个或更多单词时,如果正则表达式可以保留整个前两个单词,那将是一个福音......(例如“Kim Jong U.”)。

regex string preg-replace preg-match substr
4个回答
4
投票

可以使用正则表达式在单个

preg_replace
中完成。

您可以使用此正则表达式进行搜索:

^\w+(?:$| +)(*SKIP)(*F)|(\w)\w+

并替换为:

$1.

正则表达式演示

代码:

$name = preg_replace('/^\w+(?:$| +)(*SKIP)(*F)|(\w)\w+/', '$1.', $name);

说明:

  • (*FAIL)
    的行为类似于失败的否定断言,是
    (?!)
  • 的同义词
  • (*SKIP)
    定义了一个点,当子模式稍后失败时,正则表达式引擎将不允许回溯到该点
  • (*SKIP)(*FAIL)
    一起提供了一个很好的限制替代方案,即在上面的正则表达式中不能有可变长度的lookbehind。
  • ^\w+(?:$| +)(*SKIP)(*F)
    匹配名称中的第一个单词并跳过它(不执行任何操作)
  • (\w)\w+
    匹配所有其他单词,并将其替换为第一个字母和一个点。

1
投票

您可以使用积极的后向断言。

(?<=\h)([A-Z])\w+

如果您想将

Bob F
转换为
Bob F.

,请使用此正则表达式
(?<=\h)([A-Z])\w*(?!\.)

然后将匹配的字符替换为

\1.

演示

代码如下,

preg_replace('~(?<=\h)([A-Z])\w+~', '\1.', $string);

演示

  • (?<=\h)([A-Z])
    捕获前面有水平空格字符的所有大写字母。

  • \w+
    匹配一个或多个单词字符。

  • 将匹配的字符替换为组索引 1 中的字符

    \1
    加一个点即可得到所需的输出。


0
投票

仅具有前瞻和字边界检查的简单解决方案:

preg_replace('~(?!^)\b(\w)\w+~', '$1.', $string);
  • (\w)\w+
    是名称中的一个单词,捕获第一个字符
  • (?!^)\b
    执行单词边界检查
    \b
    ,并确保匹配项不在字符串的开头
    (?!^)

演示


0
投票

只需从字符串的最后一个(非第一个)单词的第二个字符开始匹配 - 然后用点替换该匹配(不需要捕获或引用)。

匹配文字空格,然后

\w
匹配单词字符,然后用
\K
忘记这些字符,然后匹配零个或多个单词字符,直到字符串末尾,以确保所有姓氏在第一个字母后被截断并在末尾添加一个点。

代码:(演示

$strings = [
    'John Smith',
    'John Doe',
    'David X. Cohen',
    'Kim Jong Un',
    'Bob',
];

var_export(
    preg_replace('/ \w\K\w*$/', '.', $strings)
);
© www.soinside.com 2019 - 2024. All rights reserved.