繁体   English   中英

为什么我不能在单词边界旁边使用重音字符?

[英]Why can't I use accented characters next to a word boundary?

我正在尝试制作一个与人名匹配的动态正则表达式。 它对大多数名字都没有问题,直到我在名字末尾遇到重音字符。

例子:一些花哨的名字

到目前为止我使用的正则表达式是:

/\b(Fancy Namé|Namé)\b/i

像这样使用:

"Goal: Some Fancy Namé. Awesome.".replace(/\b(Fancy Namé|Namé)\b/i, '<a href="#">$1</a>');

这根本不匹配。 如果我用 ae 替换 é,它匹配得很好。 如果我尝试匹配诸如“Some Fancy Naméa”之类的名称,它就可以正常工作。 如果我删除单词 last word 边界锚点,它就可以正常工作。

为什么边界标志这个词在这里不起作用? 关于如何解决这个问题的任何建议?

我考虑过使用这样的东西,但我不确定性能损失会是什么样的:

"Some fancy namé. Allow me to ellaborate.".replace(/([\s.,!?])(fancy namé|namé)([\s.,!?]|$)/g, '$1<a href="#">$2</a>$3')

建议? 想法?

JavaScript 的正则表达式实现不支持 Unicode。 它只知道标准低字节 ASCII 中的“单词字符”,不包括é或任何其他带重音或非英语的字母。

因为é对 JS 来说不是一个单词字符,所以é后跟一个空格永远不能被认为是一个单词边界。 (如果在单词中间使用它会匹配\\b ,比如Namés 。)

/([\\s.,!?])(fancy namé|namé)([\\s.,!?]|$)/

是的,这将是 JS 的常用解决方法(尽管可能带有更多标点符号)。 对于其他语言,您通常会使用前瞻/后视来避免匹配前后边界字符,但这些在 JS 中的支持很差/有问题,因此最好避免。

罗布是对的。 引自 ECMAScript 3rd edition:

15.10.2.6 断言:

生产断言\\b评估...

2.调用IsWordChar(e−1)并让a成为布尔结果
3.调用IsWordChar(e)并让b为布尔结果

内部辅助函数IsWordChar ... 执行以下操作:

3.如果c是下表中的 63 个字符之一,则返回true

 abcdefghijklmnopqrstu vwxyz ABCDEFGHIJKLMNOPQRSTU VWXYZ 0 1 2 3 4 5 6 7 8 9 _

由于é不是这 63 个字符之一,因此éa之间的位置将被视为单词边界。

如果您知道字符的类别,则可以使用否定的前瞻断言,例如

/(^|[^\wÀ-ÖØ-öø-ſ])(Fancy Namé|Namé)(?![\wÀ-ÖØ-öø-ſ])/

了解你的界限

不幸的是,即使有一天 Javascript 能够完全和适当地支持 Unicode,您仍然必须非常小心地处理单词边界。 很容易误解\\b真正作用。

下面是解释\\b真正在做什么的 Perl 代码,无论您的模式引擎是否已经进行了 BNM 升级,这都是正确的:

  # if next is word char:
  #     then last isn't    word
  #     else last isn't nonword

    $word_boundary_before = qr{ (?(?=  \w ) (?<! \w ) | (?<! \W ) ) }x;

  # if last is word:
  #     then next isn't    word
  #     else next isn't nonword

    $word_boundary_after  = qr{ (?(?<= \w ) (?!  \w ) | (?!  \W ) ) }x;

第一个就像在某事之前的\\b ,第二个就像在它之后的\\b 使用的构造是正则表达式“IF-THEN=ELSE”条件,它是一般形式(?(COND)THEN|ELSE) 在这里,我使用的是COND测试,它在第一种情况下是前瞻,而在第二种情况下是前瞻。 两种情况下的THENELSE子句都是否定的环视,以便它们考虑字符串的边缘。

我在这里解释了更多关于在正则表达式中处理边界和 Unicode 的信息

Unicode 属性支持

Javascript 对 Unicode 的处理当前状态似乎与 Java 一样,Javascript 对\\w的定义等仍然被困在 1960 年代的 ASCII 世界中。 我承认,这只是一种悲惨的情况。 即使是在这些事情上非常保守的 Python(例如,它甚至不支持递归正则表达式),也确实允许其对\\w\\s定义在 Unicode 上正确工作。 这是最低限度的功能水平,真的。

它在 Javascript 中既好又坏。 这是因为您可以在 Javascript(或 Java)中使用一些最基本的 Unicode 属性。 看起来您应该能够使用一个和两个字符的“通用类别”Unicode 属性。 这意味着您应该能够使用下面第一列中的短名称版本:

Short Name  Long Name
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
 \pL        \p{Letter}
   \p{Lu}   \p{Uppercase_Letter}
   \p{Ll}   \p{Lowercase_Letter}
   \p{Lt}   \p{Titlecase_Letter}
   \p{Lm}   \p{Modifier_Letter}
   \p{Lo}   \p{Other_Letter}

Short Name  Long Name
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
 \pM       \p{Mark}
   \p{Mn}  \p{Nonspacing_Mark}
   \p{Mc}  \p{Spacing_Mark}
   \p{Me}  \p{Enclosing_Mark}

Short Name  Long Name
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
 \pN       \p{Number}
   \p{Nd}  \p{Decimal_Number},\p{Digit}
   \p{Nl}  \p{Letter_Number}
   \p{No}  \p{Other_Number}

Short Name  Long Name
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
 \pP       \p{Punctuation}, \p{Punct})
   \p{Pc}  \p{Connector_Punctuation}
   \p{Pd}  \p{Dash_Punctuation}
   \p{Ps}  \p{Open_Punctuation}
   \p{Pe}  \p{Close_Punctuation}
   \p{Pi}  \p{Initial_Punctuation}
   \p{Pf}  \p{Final_Punctuation}
   \p{Po}  \p{Other_Punctuation}

Short Name  Long Name
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
 \pS       \p{Symbol}
   \p{Sm}  \p{Math_Symbol}
   \p{Sc}  \p{Currency_Symbol}
   \p{Sk}  \p{Modifier_Symbol}
   \p{So}  \p{Other_Symbol}

Short Name  Long Name
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
 \pZ       \p{Separator}
   \p{Zs}  \p{Space_Separator}
   \p{Zl}  \p{Line_Separator}
   \p{Zp}  \p{Paragraph_Separator}

Short Name  Long Name
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
 \pC       \p{Other}
   \p{Cc}  \p{Control}, \p{Cntrl}
   \p{Cf}  \p{Format}
   \p{Cs}  \p{Surrogate}
   \p{Co}  \p{Private_Use}
   \p{Cn}  \p{Unassigned}

您必须仅在 Java 和 Javascript 中使用短名称,但 Perl 也允许您使用长名称,这有助于易读性,Perl 5.12 版本支持大约 3,000 个 Unicode 属性。 Python仍然没有任何值得一提的 Unicode 属性支持,而 Ruby 才刚刚开始在 1.9 版本中获得它。 PCRE 有一些有限的支持,主要类似于 Java 1.7。

Java6 支持 Unicode 块属性,如\\p{InGeneralPunctuation}\\p{Block=GeneralPunctuation} ,Java7 支持 Unicode 脚本属性,如\\p{IsHiragana}\\p{Script=Hiragana}

然而,它仍然不支持任何甚至接近全部 Unicode 属性的东西,包括接近关键的属性,如\\p⁠{WhiteSpace}\\p{Dash}\\p{Quotation_Mark} ,更不用说其他两个了-parters 像\\p⁠{Line_Break=Alphabetic}\\p⁠{East_Asian_Width:Narrow}\\p⁠{Numeric_Value=1000}\\p⁠⁠{Age:5.2}

前一组是必不可少的——尤其是在缺乏对\\s正常工作的支持的情况下——而后一组有时非常有用。

Java 和 Javascript 尚不支持的其他内容是用户定义的字符属性 我经常使用这些。 这样你就可以定义像\\p⁠{English::Vowel}\\p⁠{English::Consonant} ,这非常方便。

如果你有兴趣在Unicode属性的正则表达式的工作,土特产品可能要抢的程序unitrio套件: uniprops单字符uninames 这是这三个中的每一个的演示:

$ uninames face
 ፦  4966  1366  ETHIOPIC PREFACE COLON
 ⁙  8281  2059  FIVE DOT PUNCTUATION
        = Greek pentonkion
        = quincunx
        x (die face-5 - 2684)
 ∯  8751  222F  SURFACE INTEGRAL
        # 222E 222E
 ☹  9785  2639 WHITE FROWNING FACE
 ☺  9786  263A WHITE SMILING FACE
        = have a nice day!
 ☻  9787  263B BLACK SMILING FACE
 ⚀  9856  2680 DIE FACE-1
 ⚁  9857  2681 DIE FACE-2
 ⚂  9858  2682 DIE FACE-3
 ⚃  9859  2683 DIE FACE-4
 ⚄  9860  2684 DIE FACE-5
 ⚅  9861  2685 DIE FACE-6
 ⾯  12207 2FAF KANGXI RADICAL FACE
        # 9762
 〠  12320 3020 POSTAL MARK FACE
 龜  64206 FACE CJK COMPATIBILITY IDEOGRAPH-FACE
        : 9F9C

FMTEYEWTK 关于 Unicode 属性:

$ uniprops -va LF 85 Greek:Sigma INFINITY BOM U+3000 U+12345

U+000A ‹U+000A› \N{ LINE FEED (LF) }:
    \s \v \R \pC \p{Cc}
    \p{All} \p{Any} \p{ASCII} \p{Assigned} \p{C} \p{Other} \p{Cc} \p{Cntrl} \p{Common} \p{Zyyy} \p{Control} \p{Pat_WS} \p{Pattern_White_Space} \p{PatWS} \p{PerlSpace} \p{PosixCntrl} \p{PosixSpace} \p{Space} \p{SpacePerl} \p{VertSpace} \p{White_Space} \p{WSpace}
    \p{Age:1.1} \p{Block=Basic_Latin} \p{Bidi_Class:B} \p{Bidi_Class=Paragraph_Separator} \p{Bidi_Class:Paragraph_Separator} \p{Bc=B} \p{Block:ASCII} \p{Block:Basic_Latin} \p{Blk=ASCII} \p{Canonical_Combining_Class:0} \p{Canonical_Combining_Class=Not_Reordered}
       \p{Canonical_Combining_Class:Not_Reordered} \p{Ccc=NR} \p{Canonical_Combining_Class:NR} \p{Script=Common} \p{Decomposition_Type:None} \p{Dt=None} \p{East_Asian_Width=Neutral} \p{East_Asian_Width:Neutral} \p{Grapheme_Cluster_Break:LF} \p{GCB=LF} \p{Hangul_Syllable_Type:NA}
       \p{Hangul_Syllable_Type=Not_Applicable} \p{Hangul_Syllable_Type:Not_Applicable} \p{Hst=NA} \p{Joining_Group:No_Joining_Group} \p{Jg=NoJoiningGroup} \p{Joining_Type:Non_Joining} \p{Jt=U} \p{Joining_Type:U} \p{Joining_Type=Non_Joining} \p{Line_Break:LF} \p{Line_Break=Line_Feed}
       \p{Line_Break:Line_Feed} \p{Lb=LF} \p{Numeric_Type:None} \p{Nt=None} \p{Numeric_Value:NaN} \p{Nv=NaN} \p{Present_In:1.1} \p{Age=1.1} \p{In=1.1} \p{Present_In:2.0} \p{In=2.0} \p{Present_In:2.1} \p{In=2.1} \p{Present_In:3.0} \p{In=3.0} \p{Present_In:3.1} \p{In=3.1}
       \p{Present_In:3.2} \p{In=3.2} \p{Present_In:4.0} \p{In=4.0} \p{Present_In:4.1} \p{In=4.1} \p{Present_In:5.0} \p{In=5.0} \p{Present_In:5.1} \p{In=5.1} \p{Present_In:5.2} \p{In=5.2} \p{Script:Common} \p{Sc=Zyyy} \p{Script:Zyyy} \p{Sentence_Break:LF} \p{SB=LF} \p{Word_Break:LF}
       \p{WB=LF}

U+0085 ‹U+0085› \N{ NEXT LINE (NEL) }:
    \s \v \R \pC \p{Cc}
    \p{All} \p{Any} \p{Assigned} \p{InLatin1} \p{C} \p{Other} \p{Cc} \p{Cntrl} \p{Common} \p{Zyyy} \p{Control} \p{Pat_WS} \p{Pattern_White_Space} \p{PatWS} \p{Space} \p{SpacePerl} \p{VertSpace} \p{White_Space} \p{WSpace}
    \p{Age:1.1} \p{Bidi_Class:B} \p{Bidi_Class=Paragraph_Separator} \p{Bidi_Class:Paragraph_Separator} \p{Bc=B} \p{Block:Latin_1} \p{Block=Latin_1_Supplement} \p{Block:Latin_1_Supplement} \p{Blk=Latin1} \p{Canonical_Combining_Class:0} \p{Canonical_Combining_Class=Not_Reordered}
       \p{Canonical_Combining_Class:Not_Reordered} \p{Ccc=NR} \p{Canonical_Combining_Class:NR} \p{Script=Common} \p{Decomposition_Type:None} \p{Dt=None} \p{East_Asian_Width=Neutral} \p{East_Asian_Width:Neutral} \p{Grapheme_Cluster_Break:CN} \p{Grapheme_Cluster_Break=Control}
       \p{Grapheme_Cluster_Break:Control} \p{GCB=CN} \p{Hangul_Syllable_Type:NA} \p{Hangul_Syllable_Type=Not_Applicable} \p{Hangul_Syllable_Type:Not_Applicable} \p{Hst=NA} \p{Joining_Group:No_Joining_Group} \p{Jg=NoJoiningGroup} \p{Joining_Type:Non_Joining} \p{Jt=U}
       \p{Joining_Type:U} \p{Joining_Type=Non_Joining} \p{Line_Break:Next_Line} \p{Lb=NL} \p{Line_Break:NL} \p{Line_Break=Next_Line} \p{Numeric_Type:None} \p{Nt=None} \p{Numeric_Value:NaN} \p{Nv=NaN} \p{Present_In:1.1} \p{Age=1.1} \p{In=1.1} \p{Present_In:2.0} \p{In=2.0}
       \p{Present_In:2.1} \p{In=2.1} \p{Present_In:3.0} \p{In=3.0} \p{Present_In:3.1} \p{In=3.1} \p{Present_In:3.2} \p{In=3.2} \p{Present_In:4.0} \p{In=4.0} \p{Present_In:4.1} \p{In=4.1} \p{Present_In:5.0} \p{In=5.0} \p{Present_In:5.1} \p{In=5.1} \p{Present_In:5.2} \p{In=5.2}
       \p{Script:Common} \p{Sc=Zyyy} \p{Script:Zyyy} \p{Sentence_Break:SE} \p{Sentence_Break=Sep} \p{Sentence_Break:Sep} \p{SB=SE} \p{Word_Break:Newline} \p{WB=NL} \p{Word_Break:NL} \p{Word_Break=Newline}

U+03A3 ‹Σ› \N{ GREEK CAPITAL LETTER SIGMA }:
    \w \pL} \p{LC} \p{L_} \p{L&} \p{Lu}
    \p{All} \p{Any} \p{Alnum} \p{Alpha} \p{Alphabetic} \p{Assigned} \p{Greek} \p{Is_Greek} \p{InGreek} \p{Cased} \p{Cased_Letter} \p{LC} \p{Changes_When_Casefolded} \p{CWCF} \p{Changes_When_Casemapped} \p{CWCM} \p{Changes_When_Lowercased} \p{CWL} \p{Changes_When_NFKC_Casefolded}
       \p{CWKCF} \p{Lu} \p{L} \p{Gr_Base} \p{Grapheme_Base} \p{Graph} \p{GrBase} \p{Grek} \p{Greek_And_Coptic} \p{ID_Continue} \p{IDC} \p{ID_Start} \p{IDS} \p{Letter} \p{L_} \p{Uppercase_Letter} \p{Print} \p{Upper} \p{Uppercase} \p{Word} \p{XID_Continue} \p{XIDC} \p{XID_Start}
       \p{XIDS}
    \p{Age:1.1} \p{Bidi_Class:L} \p{Bidi_Class=Left_To_Right} \p{Bidi_Class:Left_To_Right} \p{Bc=L} \p{Block:Greek} \p{Block=Greek_And_Coptic} \p{Block:Greek_And_Coptic} \p{Blk=Greek} \p{Canonical_Combining_Class:0} \p{Canonical_Combining_Class=Not_Reordered}
       \p{Canonical_Combining_Class:Not_Reordered} \p{Ccc=NR} \p{Canonical_Combining_Class:NR} \p{Decomposition_Type:None} \p{Dt=None} \p{East_Asian_Width:A} \p{East_Asian_Width=Ambiguous} \p{East_Asian_Width:Ambiguous} \p{Ea=A} \p{Grapheme_Cluster_Break:Other} \p{GCB=XX}
       \p{Grapheme_Cluster_Break:XX} \p{Grapheme_Cluster_Break=Other} \p{Script=Greek} \p{Hangul_Syllable_Type:NA} \p{Hangul_Syllable_Type=Not_Applicable} \p{Hangul_Syllable_Type:Not_Applicable} \p{Hst=NA} \p{Joining_Group:No_Joining_Group} \p{Jg=NoJoiningGroup}
       \p{Joining_Type:Non_Joining} \p{Jt=U} \p{Joining_Type:U} \p{Joining_Type=Non_Joining} \p{Line_Break:AL} \p{Line_Break=Alphabetic} \p{Line_Break:Alphabetic} \p{Lb=AL} \p{Numeric_Type:None} \p{Nt=None} \p{Numeric_Value:NaN} \p{Nv=NaN} \p{Present_In:1.1} \p{Age=1.1} \p{In=1.1}
       \p{Present_In:2.0} \p{In=2.0} \p{Present_In:2.1} \p{In=2.1} \p{Present_In:3.0} \p{In=3.0} \p{Present_In:3.1} \p{In=3.1} \p{Present_In:3.2} \p{In=3.2} \p{Present_In:4.0} \p{In=4.0} \p{Present_In:4.1} \p{In=4.1} \p{Present_In:5.0} \p{In=5.0} \p{Present_In:5.1} \p{In=5.1}
       \p{Present_In:5.2} \p{In=5.2} \p{Script:Greek} \p{Sc=Grek} \p{Script:Grek} \p{Sentence_Break:UP} \p{Sentence_Break=Upper} \p{Sentence_Break:Upper} \p{SB=UP} \p{Word_Break:ALetter} \p{WB=LE} \p{Word_Break:LE} \p{Word_Break=ALetter}

U+221E ‹∞› \N{ INFINITY }:
    \pS \p{Sm}
    \p{All} \p{Any} \p{Assigned} \p{InMathematicalOperators} \p{Common} \p{Zyyy} \p{Sm} \p{S} \p{Gr_Base} \p{Grapheme_Base} \p{Graph} \p{GrBase} \p{Math} \p{Math_Symbol} \p{Pat_Syn} \p{Pattern_Syntax} \p{PatSyn} \p{Print} \p{Symbol}
    \p{Age:1.1} \p{Bidi_Class:ON} \p{Bidi_Class=Other_Neutral} \p{Bidi_Class:Other_Neutral} \p{Bc=ON} \p{Block:Mathematical_Operators} \p{Canonical_Combining_Class:0} \p{Canonical_Combining_Class=Not_Reordered} \p{Canonical_Combining_Class:Not_Reordered} \p{Ccc=NR}
       \p{Canonical_Combining_Class:NR} \p{Script=Common} \p{Decomposition_Type:None} \p{Dt=None} \p{East_Asian_Width:A} \p{East_Asian_Width=Ambiguous} \p{East_Asian_Width:Ambiguous} \p{Ea=A} \p{Grapheme_Cluster_Break:Other} \p{GCB=XX} \p{Grapheme_Cluster_Break:XX}
       \p{Grapheme_Cluster_Break=Other} \p{Hangul_Syllable_Type:NA} \p{Hangul_Syllable_Type=Not_Applicable} \p{Hangul_Syllable_Type:Not_Applicable} \p{Hst=NA} \p{Joining_Group:No_Joining_Group} \p{Jg=NoJoiningGroup} \p{Joining_Type:Non_Joining} \p{Jt=U} \p{Joining_Type:U}
       \p{Joining_Type=Non_Joining} \p{Line_Break:AI} \p{Line_Break=Ambiguous} \p{Line_Break:Ambiguous} \p{Lb=AI} \p{Numeric_Type:None} \p{Nt=None} \p{Numeric_Value:NaN} \p{Nv=NaN} \p{Present_In:1.1} \p{Age=1.1} \p{In=1.1} \p{Present_In:2.0} \p{In=2.0} \p{Present_In:2.1} \p{In=2.1}
       \p{Present_In:3.0} \p{In=3.0} \p{Present_In:3.1} \p{In=3.1} \p{Present_In:3.2} \p{In=3.2} \p{Present_In:4.0} \p{In=4.0} \p{Present_In:4.1} \p{In=4.1} \p{Present_In:5.0} \p{In=5.0} \p{Present_In:5.1} \p{In=5.1} \p{Present_In:5.2} \p{In=5.2} \p{Script:Common} \p{Sc=Zyyy}
       \p{Script:Zyyy} \p{Sentence_Break:Other} \p{SB=XX} \p{Sentence_Break:XX} \p{Sentence_Break=Other} \p{Word_Break:Other} \p{WB=XX} \p{Word_Break:XX} \p{Word_Break=Other}

U+FEFF ‹U+FEFF› \N{ ZERO WIDTH NO-BREAK SPACE }:
    \pC \p{Cf}
    \p{All} \p{Any} \p{Assigned} \p{InArabicPresentationFormsB} \p{C} \p{Other} \p{Case_Ignorable} \p{CI} \p{Cf} \p{Format} \p{Changes_When_NFKC_Casefolded} \p{CWKCF} \p{Common} \p{Zyyy} \p{Default_Ignorable_Code_Point} \p{DI} \p{Graph} \p{Print}
    \p{Age:1.1} \p{Bidi_Class:BN} \p{Bidi_Class=Boundary_Neutral} \p{Bidi_Class:Boundary_Neutral} \p{Bc=BN} \p{Block:Arabic_Presentation_Forms_B} \p{Canonical_Combining_Class:0} \p{Canonical_Combining_Class=Not_Reordered} \p{Canonical_Combining_Class:Not_Reordered} \p{Ccc=NR}
       \p{Canonical_Combining_Class:NR} \p{Script=Common} \p{Decomposition_Type:None} \p{Dt=None} \p{East_Asian_Width=Neutral} \p{East_Asian_Width:Neutral} \p{Grapheme_Cluster_Break:CN} \p{Grapheme_Cluster_Break=Control} \p{Grapheme_Cluster_Break:Control} \p{GCB=CN}
       \p{Hangul_Syllable_Type:NA} \p{Hangul_Syllable_Type=Not_Applicable} \p{Hangul_Syllable_Type:Not_Applicable} \p{Hst=NA} \p{Joining_Group:No_Joining_Group} \p{Jg=NoJoiningGroup} \p{Joining_Type:T} \p{Joining_Type=Transparent} \p{Joining_Type:Transparent} \p{Jt=T}
       \p{Line_Break:WJ} \p{Line_Break=Word_Joiner} \p{Line_Break:Word_Joiner} \p{Lb=WJ} \p{Numeric_Type:None} \p{Nt=None} \p{Numeric_Value:NaN} \p{Nv=NaN} \p{Present_In:1.1} \p{Age=1.1} \p{In=1.1} \p{Present_In:2.0} \p{In=2.0} \p{Present_In:2.1} \p{In=2.1} \p{Present_In:3.0}
       \p{In=3.0} \p{Present_In:3.1} \p{In=3.1} \p{Present_In:3.2} \p{In=3.2} \p{Present_In:4.0} \p{In=4.0} \p{Present_In:4.1} \p{In=4.1} \p{Present_In:5.0} \p{In=5.0} \p{Present_In:5.1} \p{In=5.1} \p{Present_In:5.2} \p{In=5.2} \p{Script:Common} \p{Sc=Zyyy} \p{Script:Zyyy}
       \p{Sentence_Break:FO} \p{Sentence_Break=Format} \p{Sentence_Break:Format} \p{SB=FO} \p{Word_Break:FO} \p{Word_Break=Format} \p{Word_Break:Format} \p{WB=FO}

U+3000 ‹U+3000› \N{ IDEOGRAPHIC SPACE }:
    \s \h \pZ \p{Zs}
    \p{All} \p{Any} \p{Assigned} \p{Blank} \p{InCJKSymbolsAndPunctuation} \p{Changes_When_NFKC_Casefolded} \p{CWKCF} \p{Common} \p{Zyyy} \p{Z} \p{Zs} \p{Gr_Base} \p{Grapheme_Base} \p{GrBase} \p{HorizSpace} \p{Print} \p{Separator} \p{Space} \p{Space_Separator} \p{SpacePerl}
       \p{White_Space} \p{WSpace}
    \p{Age:1.1} \p{Bidi_Class:White_Space} \p{Bc=WS} \p{Bidi_Class:WS} \p{Bidi_Class=White_Space} \p{Block:CJK_Symbols_And_Punctuation} \p{Canonical_Combining_Class:0} \p{Canonical_Combining_Class=Not_Reordered} \p{Canonical_Combining_Class:Not_Reordered} \p{Ccc=NR}
       \p{Canonical_Combining_Class:NR} \p{Script=Common} \p{Decomposition_Type:Non_Canon} \p{Decomposition_Type=Non_Canonical} \p{Decomposition_Type:Non_Canonical} \p{Dt=NonCanon} \p{Decomposition_Type:Wide} \p{Dt=Wide} \p{East_Asian_Width:F} \p{East_Asian_Width=Fullwidth}
       \p{East_Asian_Width:Fullwidth} \p{Ea=F} \p{Grapheme_Cluster_Break:Other} \p{GCB=XX} \p{Grapheme_Cluster_Break:XX} \p{Grapheme_Cluster_Break=Other} \p{Hangul_Syllable_Type:NA} \p{Hangul_Syllable_Type=Not_Applicable} \p{Hangul_Syllable_Type:Not_Applicable} \p{Hst=NA}
       \p{Joining_Group:No_Joining_Group} \p{Jg=NoJoiningGroup} \p{Joining_Type:Non_Joining} \p{Jt=U} \p{Joining_Type:U} \p{Joining_Type=Non_Joining} \p{Line_Break:ID} \p{Line_Break=Ideographic} \p{Line_Break:Ideographic} \p{Lb=ID} \p{Numeric_Type:None} \p{Nt=None}
       \p{Numeric_Value:NaN} \p{Nv=NaN} \p{Present_In:1.1} \p{Age=1.1} \p{In=1.1} \p{Present_In:2.0} \p{In=2.0} \p{Present_In:2.1} \p{In=2.1} \p{Present_In:3.0} \p{In=3.0} \p{Present_In:3.1} \p{In=3.1} \p{Present_In:3.2} \p{In=3.2} \p{Present_In:4.0} \p{In=4.0} \p{Present_In:4.1}
       \p{In=4.1} \p{Present_In:5.0} \p{In=5.0} \p{Present_In:5.1} \p{In=5.1} \p{Present_In:5.2} \p{In=5.2} \p{Script:Common} \p{Sc=Zyyy} \p{Script:Zyyy} \p{Sentence_Break:Sp} \p{SB=Sp} \p{Word_Break:Other} \p{WB=XX} \p{Word_Break:XX} \p{Word_Break=Other}

U+12345 ‹𒍅› \N{ CUNEIFORM SIGN URU TIMES KI }:
    \w} \p{\pL} \p{L_} \p{Lo}
    \p{All} \p{Any} \p{Alnum} \p{Alpha} \p{Alphabetic} \p{Assigned} \p{InCuneiform} \p{Cuneiform} \p{Is_Cuneiform} \p{Xsux} \p{L} \p{Lo} \p{Gr_Base} \p{Grapheme_Base} \p{Graph} \p{GrBase} \p{ID_Continue} \p{IDC} \p{ID_Start} \p{IDS} \p{Letter} \p{L_} \p{Other_Letter} \p{Print}
       \p{Word} \p{XID_Continue} \p{XIDC} \p{XID_Start} \p{XIDS}
    \p{Age:5.0} \p{Bidi_Class:L} \p{Bidi_Class=Left_To_Right} \p{Bidi_Class:Left_To_Right} \p{Bc=L} \p{Block:Cuneiform} \p{Canonical_Combining_Class:0} \p{Canonical_Combining_Class=Not_Reordered} \p{Canonical_Combining_Class:Not_Reordered} \p{Ccc=NR}
       \p{Canonical_Combining_Class:NR} \p{Script=Cuneiform} \p{Block=Cuneiform} \p{Decomposition_Type:None} \p{Dt=None} \p{East_Asian_Width=Neutral} \p{East_Asian_Width:Neutral} \p{Grapheme_Cluster_Break:Other} \p{GCB=XX} \p{Grapheme_Cluster_Break:XX}
       \p{Grapheme_Cluster_Break=Other} \p{Hangul_Syllable_Type:NA} \p{Hangul_Syllable_Type=Not_Applicable} \p{Hangul_Syllable_Type:Not_Applicable} \p{Hst=NA} \p{Joining_Group:No_Joining_Group} \p{Jg=NoJoiningGroup} \p{Joining_Type:Non_Joining} \p{Jt=U} \p{Joining_Type:U}
       \p{Joining_Type=Non_Joining} \p{Line_Break:AL} \p{Line_Break=Alphabetic} \p{Line_Break:Alphabetic} \p{Lb=AL} \p{Numeric_Type:None} \p{Nt=None} \p{Numeric_Value:NaN} \p{Nv=NaN} \p{Present_In:5.0} \p{In=5.0} \p{Present_In:5.1} \p{In=5.1} \p{Present_In:5.2} \p{In=5.2}
       \p{Script:Cuneiform} \p{Sc=Xsux} \p{Script:Xsux} \p{Sentence_Break:LE} \p{Sentence_Break=OLetter} \p{Sentence_Break:OLetter} \p{SB=LE} \p{Word_Break:ALetter} \p{WB=LE} \p{Word_Break:LE} \p{Word_Break=ALetter}

或者,走另一条路:

$ unichars '\pN' '\D' '\p{Latin}'
 Ⅰ      8544  02160  ROMAN NUMERAL ONE
 Ⅱ      8545  02161  ROMAN NUMERAL TWO
 Ⅲ      8546  02162  ROMAN NUMERAL THREE
 Ⅳ      8547  02163  ROMAN NUMERAL FOUR
 Ⅴ      8548  02164  ROMAN NUMERAL FIVE
 Ⅵ      8549  02165  ROMAN NUMERAL SIX
 Ⅶ      8550  02166  ROMAN NUMERAL SEVEN
 Ⅷ      8551  02167  ROMAN NUMERAL EIGHT
 (etc)

$ unichars -a '\pL' '\p{Greek}' 'NFD ne NFKD' 'NAME =~ /SYMBOL/'
 ϐ       976  3D0  GREEK BETA SYMBOL
 ϑ       977  3D1  GREEK THETA SYMBOL
 ϒ       978  3D2  GREEK UPSILON WITH HOOK SYMBOL
 ϓ       979  3D3  GREEK UPSILON WITH ACUTE AND HOOK SYMBOL
 ϔ       980  3D4  GREEK UPSILON WITH DIAERESIS AND HOOK SYMBOL
 ϕ       981  3D5  GREEK PHI SYMBOL
 ϖ       982  3D6  GREEK PI SYMBOL
 ϰ      1008  3F0  GREEK KAPPA SYMBOL
 ϱ      1009  3F1  GREEK RHO SYMBOL
 ϲ      1010  3F2  GREEK LUNATE SIGMA SYMBOL
 ϴ      1012  3F4  GREEK CAPITAL THETA SYMBOL
 ϵ      1013  3F5  GREEK LUNATE EPSILON SYMBOL
 Ϲ      1017  3F9  GREEK CAPITAL LUNATE SIGMA SYMBOL

哦, BNM 的意思是“勇敢的新千年” ,指的是我们现代的后 ASCII 世界,在这个世界中,字符的宽度超过了微不足道的 7 位。

String.replace() 接受回调函数作为它的第二个参数。 (不知道为什么这么多JS教程都省略了这个有用的功能。)因此,我们可以编写自己的单词边界测试。

在别处提出的解决方案,使用正则表达式/(\\W|^)(fancy namé|namé)(\\W|$)/ig ,在诸如“nameé”之类的文本的情况下给出误报。

String.prototype.isWordCharAt = function(i) {
    // should work for European languages and Unicode
    return (this.charAt(i) >= 'A' && this.charAt(i) <= 'Z')
        || (this.charAt(i) >= 'a' && this.charAt(i) <= 'z')
        || (this.charCodeAt(i) >= 0xC0 && this.charCodeAt(i) < 0x2000)
    ;
};

"Namé. Goal: Some Fancy Namé. Namé. Nénamé. Namée. Nénamée. Namé"
.replace(/(Namé|Fancy Namé)/ig, function(
match, part1, /* part2, part3, ... */ offset, fullText) {
  // Keep in mind that the number of arguments changes
  // if the number of capturing parenthesis in regexp changes.
  // We could use 'arguments' pseudo-array instead.
  var len1 = part1.length;
  var leftWordBoundary;
  var rightWordBoundary;

  if (offset === 0) {
    leftWordBoundary = fullText.isWordCharAt(offset);
  }
  else {
    leftWordBoundary = (fullText.isWordCharAt(offset - 1)
      != fullText.isWordCharAt(offset));
  }

  if (offset + len1 == fullText.length) {
    rightWordBoundary = fullText.isWordCharAt(offset + len1 - 1);
  }
  else {
    rightWordBoundary = (fullText.isWordCharAt(offset + len1 - 1)
      != fullText.isWordCharAt(offset + len1));
  }

  if (leftWordBoundary && rightWordBoundary) {
    return '<a href="#">' + part1 + '</a>';
  }
  else {
    return part1;
  }
});

如果你想匹配“my_word”,你可以在后面使用否定查找?<! 和负面展望?!

这将检查单词前面没有非单词字符, new RegExp(`(?<![A-Za-zÀ-ÖØ-öø-ÿ])my_word(?![A-Za-zÀ-ÖØ-öø-ÿ])`, "gi");没有非单词字符new RegExp(`(?<![A-Za-zÀ-ÖØ-öø-ÿ])my_word(?![A-Za-zÀ-ÖØ-öø-ÿ])`, "gi");

-用于 ascii 表中的间隔。 这里要检查的 Ascii 表正是您所需要的http://seamons.com/projects/js/ascii_table.html

正如其他回答者已经指出的那样,JS 正则表达式引擎不认为“é”是一个单词字符。 既然是这样,并且您想匹配该字母后跟另一个非单词字符,您可以在那里使用\\B断言

> "Goal: Some Fancy Namé. Awesome.".replace(/\b(Fancy Namé|Namé)\B/i, '<a href="#">$1</a>');
'Goal: Some <a href="#">Fancy Namé</a>. Awesome.'

如果您希望其意图显而易见,可能不是最好的代码,但它在这种情况下有效,呵呵。

也许在使用正则表达式时尝试使用\\o\\x标志。

Javascript 正则表达式参考的结尾可能会对您有所帮助。

至于实际的八进制/十六进制值é与哪些相关联,我不确定。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM