PHP正则表达式 - 移除所有非字母数字字符

12

我使用 PHP。

我的字符串可能看起来像这样

This is a string-test width åäö and some über+strange characters: _like this?

问题

有没有一种方法可以删除非字母数字字符并用空格替换它们?以下是一些非字母数字字符:

  • -
  • +
  • :
  • _
  • ?

我已经阅读了许多相关的帖子,但它们不支持其他语言,比如这个:

preg_replace("/[^A-Za-z0-9 ]/", '', $string);

要求

  • 我的非字母字符列表可能不完整。
  • 我的内容包含不同语言的字符,例如åäöü。可能还有更多。
  • 非字母数字字符应替换为空格。否则单词会粘在一起。
4个回答

33

你可以尝试这个:

preg_replace('~[^\p{L}\p{N}]++~u', ' ', $string);

\p{L} 代表所有字母字符(无论是什么字母表)。

\p{N} 代表数字。

使用 u 修饰符,主字符串中的字符将被视为 Unicode 字符。

或者是这个:

preg_replace('~\P{Xan}++~u', ' ', $string);

\p{Xan} 包含 Unicode 字母和数字。

\P{Xan} 包含除 Unicode 字母和数字之外的所有内容。(注意,它还包括空格,你可以使用 ~[^\p{Xan}\s]++~u 保留空格。)

如果您想要更具体的允许字母集合,您必须在Unicode 表中用范围替换 \p{L}

示例:

preg_replace('~[^a-zÀ-ÖØ-öÿŸ\d]++~ui', ' ', $string);

为什么在这里使用所有权量词(++)?

~\P{Xan}+~u会给您与~\P{Xan}++~u相同的结果。区别在于,在第一个正则表达式中,引擎记录了每个回溯位置(我们不需要),而在第二个正则表达式中,它没有记录(就像原子组一样)。结果是获得了一点性能提升。

我认为在可能的情况下使用所有权量词和原子组是一个好习惯。

然而,PCRE正则表达式引擎会自动将显而易见的情况下的量词变为所有权量词(例如:a+b => a++b),除非使用选项PCRE_NO_AUTO_POSSESS进行编译。(http://www.pcre.org/pcre.txt

关于所有权量词和原子组的更多信息请点击此处(所有权量词)此处(原子组)或点击此处


这个。然而,根据字符串的不同,有些人可能想要包括\X - Wrikken
@CasimiretHippolyte 感谢您的帖子,它对我很有帮助。我喜欢您的正则表达式 preg_replace('[^a-zÀ-ÖØ-öÿŸ\d]++ui', ' ', $string); 但我想知道如何在字符串中添加“_”下划线和“-”连字符以保留。 - MZaragoza
@MoisesZaragoza:如果你想保留这些字符,只需要将它们添加到字符类中,因为它是一个负字符类(由于开头的 ^,只有不在该类中的字符才会被匹配和替换)。所以可以使用 ~[^a-zÀ-ÖØ-öÿŸ\d_-]++~ui~[^\p{L}\p{N}_-]++~u~[^\p{Xan}_-]++~u - Casimir et Hippolyte
@MoisesZaragoza:请注意,在Ruby中,您可以使用\p{alnum}(表示所有Unicode字母和数字)和类交集:[\P{alnum}&&[^_-]] - Casimir et Hippolyte

3

您也许正在寻找 \W

类似这样的东西:

/[\W_]*/

匹配所有非字母数字字符和下划线。

\w 匹配所有单词字符(字母、数字、下划线)

\W 匹配任何不在 \w 中的字符。

因此,\W 匹配任何非字母数字字符,并添加下划线,因为 \W 不匹配下划线。

编辑:这将使您的代码行变成:

preg_replace("/[\W_]*/", ' ', $string);
' '表示所有匹配字符(既不是字母也不是数字)都将变成空格。
重新编辑:您可能还需要使用另一个preg_replace函数来删除所有连续的空格并将它们替换为一个空格,否则您最终会得到:
This is a string test width     and some  ber strange characters   like this 

您可以使用:

preg_replace("/\s+/", ' ', $string);

最后,如有空格,请修剪开头和结尾的空格。

2

我不确定您正在使用哪种正则表达式。但是,POSIX正则表达式允许您表达字母类,其中[:alpha:]代表任何字母字符。

因此,请尝试:

preg_replace("/[^[:alpha:]0-9 ]/", '', $string);

其实,我忘记了[:alnum:] - 这使得它更简单:

preg_replace("/[^[:alnum:] ]/", '', $string);

1

\p{xx} 是你正在寻找的,我相信,在这里查看

所以,请尝试:

preg_replace("/\P{L}+/u", ' ', $string);

但这难道不会将原帖想留下的所有字母字符都替换为空格吗? - Jerry
这不应替换任何字母字符,不要(注意大写P)。 - femtoRgon
哦,对了。那么数字字符呢?它们包含在 L 中吗?我不确定文档中的“修饰字母”或“其他字母”是什么意思。 - Jerry

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接