我的目标是通过将女性名词(德语)包装成具有特定<span>
样式的class="..."
标记来突出显示女性名词。
由于我正在处理一个非ASCII集合,我(遗憾的是)我不能在JavaScript的RegEx中使用“字边界”\b
所以我被迫通过明确列出我认为是一个单词的即兴创作边界。
我的代码(简化和简化)如下所示:
const wordBoundary = "(^|\\s|$|/|\\?|\\.|\\!|\\ )";
"Liebe Grüße".replace(
new RegExp(`${wordBoundary}(Liebe|Grüße)${wordBoundary}`, "g"),
`<span class="nounF">$1$2$3</span>`
);
但是,这只会突出显示第一个单词,而不是第二个单词,生成
<span class="nounF">Liebe </span>Grüße
。
在控制台中进行调试我(几乎是偶然的)发现如果不使用RegExp
对象我使用正则表达式初始化程序 - 一切都按预期工作,生成
<span class="nounF">Liebe</span> <span class="nounF">Grüße</span>
:
"Liebe Grüße".replace(
/(^|\\s|$|\/|\\?|\\.|\\!|\\ )(Liebe|Grüße)(^|\\s|$|\/|\\?|\\.|\\!|\\ )/g,
`<span class="nounF">$1$2$3</span>`
);
我的问题是双重的:
RegExp
对象而不是使用就地正则表达式初始化程序做错了吗?因为这对我来说就像一个小虫,TBH wordBoundary
?答案 0 :(得分:2)
首先让我们考虑你的单词边界:
const wordBoundary = "(^|\\s|$|/|\\?|\\.|\\!|\\ )";
与其他地方所声称的相反, 正确转义。它不一定是编写它的最佳方式,但它会起作用。最后空格的|\\ )
是必要的,因为\\s
&gt;已经涵盖了!
&gt;你也不需要逃离const wordBoundary = "(^|\\s|$|/|\\?|\\.|\\!|\\ )";
console.log(
"cat dog".match(new RegExp(`${wordBoundary}(cat|dog)${wordBoundary}`, 'g'))
);
,但它不会受到伤害。
让我们考虑一个仅使用ASCII的类似示例:
cat
&#13;
请注意,它仅匹配dog
而非'cat '
。或者更确切地说,它匹配dog
,最后有一个空格。这是关键。该空间已匹配,因此您在尝试匹配const wordBoundary = "(^|\\s|$|/|\\?|\\.|\\!|\\ )";
console.log(
"cat dog".match(new RegExp(`${wordBoundary}(cat|dog)(?=${wordBoundary})`, 'g'))
);
时无法再次匹配该空间。匹配不能重叠。为了避免这个问题,你要使用积极的先行来确保不占用空间:
cat
&#13;
更好,现在它匹配dog
和' dog'
。注意空格现在是const wordBoundary = '[\\s/?.!]';
var re = new RegExp(`(^|${wordBoundary})(Liebe|Grüße|Ärztin)(?=${wordBoundary}|$)`, 'g');
console.log(re);
// Test cases
[
'Liebe Grüße',
'Liebe asGrüße Liebe Grüße Ärztin Grüße bd',
'Liebe GrüßeLiebe Grüße Ärztin Grüße bd',
'Liebe Grüßeas Liebe Grüße Ärztin Grüße bd',
'Liebe as Grüße Liebe Grüße Ärztin Grüße bd',
'Liebe Ärztin Grüße',
'Liebe\nGrüße',
'Liebe\tGrüße',
'Liebe?Grüße',
'Liebe.Grüße',
'Liebe!Grüße',
'Liebe/Grüße',
'Liebe\\Grüße'
].forEach(function(str) {
console.log(str.replace(re, '$1<b>$2</b>'));
});
的开头,因为它是第二个匹配的一部分,而不是第一个匹配的一部分。
为了回到原来的例子我们可以这样写:
// This is the same as:
// var re = new RegExp('(\\\\?)(Liebe|Grüße)(\\\\?)', 'g');
var re = /(\\?)(Liebe|Grüße)(\\?)/g;
console.log("Liebe Grüße".replace(re, `<b>$1$2$3</b>`));
console.log("LiebeXX Grüße".replace(re, `<b>$1$2$3</b>`));
console.log("Liebe\\Grüße".replace(re, `<b>$1$2$3</b>`));
&#13;
虽然我已经改变了在该示例中编写单词边界的方式,但应该注意的是,完全按照在问题中编写的方式编写它也可以正常工作。
这留下了一个悬而未决的问题:为什么额外的转义似乎有效?这是一个更简单的例子来帮助证明:
\\?
&#13;
我已经删除了大部分字边界,并且刚刚离开了交替的关键部分?
。双斜杠是单斜杠的转义序列,而\
被视为&#39;可选&#39;修改。所以这匹配一个可选的\
。换句话说,单词边界将非常愉快地匹配空字符串。实际上它只是完全忽略了单词边界,除非该边界是 import requests
file_name = "s_shot"
app = wx.App()
screen = wx.ScreenDC()
size = screen.GetSize()
bmp = wx.EmptyBitmap(size[0], size[1])
mem = wx.MemoryDC(bmp)
mem.Blit(0,0,size[0], size[1], screen, 0, 0)
del mem
# capture screen and save it to file
my_file = '{}{}{}'.format(file_name,i,'.png')
bmp.SaveFile(my_file, wx.BITMAP_TYPE_PNG)
i+=1
url = '127.0.0.1:30000/file'
files = {'media': open(my_file, 'rb')}
requests.post(url, files=files)
字符。
当您使用字符串创建RegExp时,您需要转义一个额外的斜杠(一次用于字符串文字,一次用于RegExp)。但是,您在原始示例中已经这样做了。通过再次逃避它们(这样你有4个斜线),你最终只能得到一个可选的斜线&#39;场景。
答案 1 :(得分:0)
你必须加倍反斜杠:
const wordBoundary = "(^|\\\\s|$|/|\\\\?|\\\\.|\\\\!|\\\\ )";
这是因为(在您的场景中)变量wordBoundary
包含正确转义的反斜杠(\\
),但是当您在${...}
中再次重用该变量时,您将失去转义(所有{ {1}}已成为\\
,现在你逃脱了其他角色)。 RegExp文字完全避免了这个问题。