Por que não posso usar caracteres acentuados ao lado de um limite do Word?
-
20-09-2019 - |
Pergunta
Estou tentando fazer um regex dinâmico que corresponda ao nome de uma pessoa. Funciona sem problemas na maioria dos nomes, até que eu encontrei caracteres acentuados no final do nome.
Exemplo: algum namé chique
O regex que usei até agora é:
/\b(Fancy Namé|Namé)\b/i
Usado assim:
"Goal: Some Fancy Namé. Awesome.".replace(/\b(Fancy Namé|Namé)\b/i, '<a href="#">$1</a>');
Isso simplesmente não corresponde. Se eu substituir o É por AE, ele corresponde muito bem. Se eu tentar combinar um nome como "algum naméa sofisticado", funciona muito bem. Se eu remover a palavra âncora da última palavra, ela funciona muito bem.
Por que a palavra bandeira de limite não funciona aqui? Alguma sugestão de como eu contoraria esse problema?
Eu pensei em usar algo assim, mas não tenho certeza de como seriam as penalidades de desempenho:
"Some fancy namé. Allow me to ellaborate.".replace(/([\s.,!?])(fancy namé|namé)([\s.,!?]|$)/g, '$1<a href="#">$2</a>$3')
Sugestões? Ideias?
Solução
A implementação do Regex do JavaScript não é consciente do Unicode. Ele só conhece as 'personagens da palavra' no ASCII de baixo byte padrão, que não inclui é
ou quaisquer outras cartas acentuadas ou não inglesas.
Porque é
não é um personagem de palavra para JS, é
Seguido por um espaço nunca pode ser considerado um limite de palavra. (Isso corresponderia \b
se usado no meio de uma palavra, como Namés
.)
/([\s.,!?])(fancy namé|namé)([\s.,!?]|$)/
Sim, essa seria a solução usual para JS (embora provavelmente com mais caracteres de pontuação). Para outros idiomas, você geralmente usaria o Lookahead/LookBehind para evitar a correspondência dos caracteres pré e pós -limite, mas estes são mal suportados/buggy no JS tão melhor evitado.
Outras dicas
Rob está correto. Citado na 3ª edição do ECMAScript:
15.10.2.6 Asserção:
A produção Afirmação
\b
avalia por ...2. Ligar Iswordchar (e -1) e deixar uma seja o resultado booleano
3. Ligar Iswordchar (e) e deixar b seja o resultado booleano
e
A função auxiliar interna Iswordchar ... executa o seguinte:
3. Se c é um dos sessenta e três caracteres da tabela abaixo, retornar verdadeiro.
a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 _
Desde é
não é um desses 63 caracteres, o local entre é
e a
será considerado um limite de palavra.
Se você conhece a classe de personagens, pode usar uma afirmação negativa para a aparência, por exemplo,
/(^|[^\wÀ-ÖØ-öø-ſ])(Fancy Namé|Namé)(?![\wÀ-ÖØ-öø-ſ])/
Conheça seus limites
Infelizmente, mesmo que e quando JavaScript deve algum dia ter suporte completo e adequado para o Unicode, você irá ainda tem que ter muito cuidado com os limites das palavras. É fácil entender mal o que um \b
realmente faz.
Aqui está o código Perl que explica o que \b
está realmente fazendo, o que é verdade, independentemente de o seu mecanismo de padrões ainda foi atualizado no 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;
O primeiro é como um \b
antes de algo, e o segundo é como um \b
depois disso. O construto usado é o regex “if-then = else” condicional, que é da forma geral (?(COND)THEN|ELSE)
. Aqui estou usando um Cond teste que é um lookahead no primeiro caso, mas um lookahead no segundo. o ENTÃO e SENÃO As cláusulas em ambos os casos são negadas, para que eles levem em consideração a borda da string.
Eu explico mais sobre como lidar com limites e unicode em expressões regulares aqui.
Suporte da propriedade Unicode
o estado atual de coisas no tratamento de unicode de JavaScript parece Para ser assim como Java, as definições de JavaScript de \w
e tal ainda são aleijado por estar preso na década de 1960 Mundo de ASCII. Esta é apenas uma situação miserável, admito. Até o python, o que é bastante conservador à medida que essas coisas acontecem (por exemplo, nem suporta regexes recursivos), faz permitir suas definições de \w
e \s
trabalhar no Unicode corretamente. Esse é o nível mínimo de funcionalidade mais barato, na verdade.
É melhor e pior no Javasscript. Isso é porque você posso Use algumas das propriedades mais básicas do Unicode em JavaScript (ou Java). Parece que você deve usar as propriedades Unicode de "categoria geral" de um e dois caracteres. Isso significa que você deve usar as versões de nome curto da primeira coluna abaixo:
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}
Você precisa usar os nomes curtos apenas em Java e JavaScript, mas o Perl permite usar os nomes longos também, o que ajuda a legibilidade para a liberação 5.12 do Perl suporta cerca de 3.000 propriedades Unicode. Pitão ainda Não possui nenhum suporte à propriedade Unicode que valha a pena mencionar, e Ruby está apenas começando a obtê -lo na versão 1.9. O PCRE tem um suporte limitado, principalmente como o Java 1.7.
Java6 suporta propriedades de bloco Unicode, como \p{InGeneralPunctuation}
ou \p{Block=GeneralPunctuation}
, e Java7 suporta propriedades de script Unicode, como \p{IsHiragana}
ou \p{Script=Hiragana}
.
No entanto, ainda não suporta nada perto do Conjunto completo de propriedades Unicode, incluindo os quase críticos como \p{WhiteSpace}
, \p{Dash}
, e \p{Quotation_Mark}
, muito menos os outros dois parters como \p{Line_Break=Alphabetic}
, \p{East_Asian_Width:Narrow}
, \p{Numeric_Value=1000}
, ou \p{Age:5.2}
.
O conjunto anterior é bastante indispensável - especialmente dada a falta de apoio para \s
Trabalhando corretamente - e o último conjunto é bastante útil às vezes.
Outra coisa que Java e JavaScript ainda não suportam Propriedades de caracteres definidas pelo usuário. Eu uso isso um pouco. Dessa forma, você pode definir coisas como \p{English::Vowel}
ou \p{English::Consonant}
, o que é bastante útil.
Se você estiver interessado em propriedades unicode para o trabalho regex, você pode querer pegar o Unitrio Suíte de programas: uniprops, Unichars, e não -ing. Aqui está uma demonstração de cada um desses três:
$ 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 SOBRE A UNICODE PROPRIEDADES:
$ 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}
Ou, indo para o outro lado:
$ 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
Óh, e Bnm significa “Brave New Millennium”, referindo-se ao nosso mundo moderno pós-ASCII, no qual os personagens são mais do que apenas sete pedaços insignificantes de largura. ☺
String.replace () aceita a função de retorno de chamada como seu segundo parâmetro. (Não sei por que tantos tutoriais do JS omitem esse recurso útil.) Assim, podemos escrever nosso próprio teste para os limites do Word.
A solução proposta em outro lugar, com regexp /(\W|^)(fancy namé|namé)(\W|$)/ig
, fornece falsos positivos em casos de texto como 'naméé'.
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;
}
});
Talvez tente usar o \o
ou \x
sinalizadores ao usar seu regex.
O fim de Esta referência para expressões regulares de JavaScript pode ajudá -lo.
Quanto ao que valores reais de octal/hexadecipal é
está associado a, não tenho certeza.