正则表达式删除非字母字符但保留重音字母

时间:2011-12-01 11:36:02

标签: javascript regex string diacritics

我有西班牙语和其他语言的字符串,可能包含通用特殊字符,如(),*等。我需要删除。但问题是它也可能包含特殊的语言字符,如ñ,á,ó,í等,它们需要保留。所以我试图用以下方式用regexp来做:

var desired = stringToReplace.replace(/[^\w\s]/gi, '');

不幸的是,它删除了所有特殊字符,包括相关语言。不知道如何避免这种情况。也许有人会建议?

6 个答案:

答案 0 :(得分:12)

我建议使用Steven Levithan出色的XRegExp库及其Unicode plug-in

以下是从字符串中删除非拉丁字符的示例:http://jsfiddle.net/b3awZ/1/

var regex = XRegExp("[^\\s\\p{Latin}]+", "g");
var str = "¿Me puedes decir la contraseña de la Wi-Fi?"
var replaced = XRegExp.replace(str, regex, "");

另见Steven Levithan本人的回答:

Regular expression Spanish and Arabic words

答案 1 :(得分:8)

您可以尝试将非法字符列入黑名单,而不是将您接受的字符列入白名单:

var desired = stringToReplace.replace(/[-'`~!@#$%^&*()_|+=?;:'",.<>\{\}\[\]\\\/]/gi, '')

答案 2 :(得分:7)

注意!仅适用于16位代码点。这个答案是不完整的。

简短回答

所有阿拉伯数字拉丁字母的字符类为:[0-9A-Za-z\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u02af\u1d00-\u1d25\u1d62-\u1d65\u1d6b-\u1d77\u1d79-\u1d9a\u1e00-\u1eff\u2090-\u2094\u2184-\u2184\u2488-\u2490\u271d-\u271d\u2c60-\u2c7c\u2c7e-\u2c7f\ua722-\ua76f\ua771-\ua787\ua78b-\ua78c\ua7fb-\ua7ff\ufb00-\ufb06]

要获得正则表达式,您可以使用,添加/^并添加+$/。这将匹配仅由拉丁字母和"mérito""Schönheit"等数字组成的字符串。

要匹配非数字或非字母字符以将其删除,请在左括号^之后写一个[作为第一个字符,然后添加/并附加+/

我是如何找到的?继续阅读。

答案很长:使用元编程!

因为Javascript没有Unicode正则表达式,所以我编写了一个Python程序来迭代整个Unicode并按Unicode名称进行过滤。很难手动完成这项工作。为什么不让电脑做脏兮兮的工作?

import unicodedata
import re
import sys

def unicodeNameMatch(pattern, codepoint):
  try:
    return re.match(pattern, unicodedata.name(unichr(codepoint)), re.I)
  except ValueError:
    return None

def regexChr(codepoint):
  return chr(codepoint) if 32 <= codepoint < 127 else "\\u%04x" % codepoint

names = sys.argv
prev = None

js_regex = ""
for codepoint in range(pow(2, 16)):
  if any([unicodeNameMatch(name, codepoint) for name in names]):
    if prev is None: js_regex += regexChr(codepoint)
    prev = codepoint
  else:
    if not prev is None: js_regex += "-" + regexChr(prev)
    prev = None

print "[" + js_regex + "]"

像这样调用它:python char_class.py latin digit并获得上面提到的字符类。这是一个丑陋的char类,但你知道肯定你抓住了名字包含latindigit的所有字符。

浏览Unicode Character Database以查看所有unicode字符的名称。在第一个分号后面的名称是大写的,例如A的行是

0041;LATIN CAPITAL LETTER A;Lu;0;L;;;;;N;;;;0061;

尝试python char_class.py "latin small",您就可以获得所有拉丁文小写字母的字符类。

编辑:正则表达式中\u271d-\u271d发生了一个小错误(也就是错误)。也许此修复有助于:替换

if not prev is None: js_regex += "-" + regexChr(prev)

通过

if not prev is None and prev != codepoint: js_regex += "-" + regexChr(prev)

答案 3 :(得分:1)

var desired = stringToReplace.replace(/[\u0000-\u007F][\W]/gi, '');

可能会成功。

另请参阅此Javascript + Unicode regexes问题。

答案 4 :(得分:1)

如果你必须坚持白名单,这是最简单的方法:

Test if string contains only letters (a-z + é ü ö ê å ø etc..)

它的工作原理是跟踪'所有'unicode字母字符。

答案 5 :(得分:0)

不幸的是,Javascript不支持Unicode character properties(这对您来说是正确的正则表达式功能)。如果您可以选择更改语言,PHP(例如)可以执行此操作:

preg_replace("/[^\pL0-9_\s]/", "", $str);

\pL匹配任何代表字母的Unicode字符(小写,大写,修改或未修改)。

如果你必须坚持使用JavaScript并且不能使用Tim Down建议的库,那么唯一的选择可能是黑名单或白名单。但是你的赏金提到黑名单实际上并不是你的选择。因此,您可能只需要手动包含相关语言中的特殊字符。所以你可以这样做:

var desired = stringToReplace.replace(/[^\w\sñáóí]/gi, '');

或使用相应的Unicode序列:

var desired = stringToReplace.replace(/[^\w\s\u00F1\u00C1\u00F3\u00ED]/gi, '');

然后只需添加您想要照顾的所有内容。请注意,不区分大小写的修饰符也适用于Unicode序列。