用引号替换双引号

我正在寻找一种方法来替换用户输入中“更正”引号的引号。

这个想法

这是一个简要说明原则的片段:
对于报价,“正确的”具有开头和结束 ,因此需要以良好的方式进行替换。

 $('#myInput').on("keyup", function(e) { // The below doesn't work when there's no space before or after. this.value = this.value.replace(/ "/g, ' “'); this.value = this.value.replace(/" /g, '” '); }); 
   

但上述情况并非在所有情况下都有效。
例如,当“引用的单词”位于句子或行的开头或结尾时。

例子

可能的输入(小心,法语里面!:)):
⋅我很开心! Çayest,j’ai“osé”,et mon“âmesœur”étaitaurendez-vous …
⋅标志上写着:“有些文字”有些文字“有些文字”。 并“注意这里的空间!”
⋅“Inc”或“rect”quo“tes should”不得更换。
⋅我说:“如果它也适用于’单身’,我会更喜欢它!”

正确的产出:
⋅我很开心! Çayest,j’ai“osé”,et mon“âmesœur”étaitaurendez-vous …
⋅标志上写着:“有些文字”有些文字“有些文字。”和“注意这里的空间!”
⋅“Inc”或“rect”quo“tes should”不得更换。
⋅我说:“如果它也适用于’单身’,我会更喜欢它!”

输出不正确:
⋅标志上写着:“有些文字”有些文字“有些文字。”和[…]
为什么不正确:
→报价结尾与结束标记之间不应有空格。
→在右引号和单词之间应该有一个空格。
→单词和开头引号之间应该有一个空格。
→开头引号与其报价单之间不应有空格。

需要

在所有这些情况下,如何才能有效和轻松地替换报价?
如果可能的话,我也希望解决方案能够“纠正”引号,即使我们在输入整个句子添加它们也是如此。

请注意,我不能(不能)在正则表达式中使用单词分隔符“\ b”,因为“重音字符,例如”é“或”ü“不幸被视为单词分隔符。”(来源: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions )

当然,如果没有其他解决方案,我会想出一个我认为是单词分隔符的列表并在正则表达式中使用它。 但我更喜欢有一个很好的工作function而不是列表!

任何想法将不胜感激。

它适用于许多情况,除了“单词”在句子或行的开头或结尾时。

要解决该问题,您可以使用行断言的开头/结尾和空格的交替,捕获它,并在替换中使用它:

 this.value = this.value.replace(/(^| )"/g, '$1“'); this.value = this.value.replace(/"($| )/g, '”$1'); 

交替是^| / $| 。 如果匹配断言,捕获组将为""如果匹配sapce,则为" "

 $('#myInput').on("keyup", function(e) { this.value = this.value.replace(/'/g, '''); // The below doesn't work when there's no space before or after. this.value = this.value.replace(/(^| )"/g, '$1“'); this.value = this.value.replace(/"($| )/g, '”$1'); }); 
   

我得到了一个最终满足我所有需求的解决方案。
我承认它比TJ的复杂得多,这对于简单的情况来说是完美的。

请记住,我的主要问题是因为重音字符而使用\b的不平衡。
通过使用本主题的解决方案,我能够摆脱这个问题:
在JavaScript中删除字符串中的重音符号/变音符号

在那之后,我使用了一个修改过的function,其灵感来自于这里的答案……
如何在JavaScript中替换特定索引处的字符?

…并且非常艰难,与RegEx一起玩很多以最终获得该解决方案:

 var str_orig = `· I'm "happy" ! Ça y est, j'ai "osé", et mon "âme sœur" était au rendez-vous… · The sign says: "Some text "some text" some text." and "Note the space here !" ⋅ "Inc"or"rect" quo"tes should " not be replaced. · I said: "If it works on 'singles' too, I'd love it even more!" word1" word2" word1 word2" "word1 word2 "word1" word2 "word1" word2" "word1 word2"`; // Thanks, exactly what I needed! var str_norm = str_orig.normalize('NFD').replace(/[\u0300-\u036f]/g, ''); // Thanks for inspiration String.prototype.replaceQuoteAt = function(index, shift) { const replacers = "“'”'"; var offset = 1 * (this[index] == "'") + 2 * (shift); return this.substr(0, index) + replacers[offset] + this.substr(index + 1); } // Opening quote: not after a boundary, not before a space or at the end var re_start = /(?!\b)["'](?!(\s|$))/gi; while ((match = re_start.exec(str_norm)) != null) { str_orig = str_orig.replaceQuoteAt(match.index, false); } // Closing quote: not at the beginning or after a space, not before a boundary var re_end = /(? 

因此,我不会使用正则表达式替换方法,而是使用带引号平衡动作的简单循环。 您假设显示的每个单引号都与另一个引用匹配,当它出现时它将被替换为对。

以下是相同的测试实现

 String.prototype.replaceAt=function(index, replacement) { return this.substr(0, index) + replacement+ this.substr(index + replacement.length); } tests =[ // [`I'm "happy"! J'ai enfin "osé". La rencontre de mon "âme-sœur" a "été" au rendez-vous… // and how it should look after correction:`, `I'm "happy"! J'ai enfin "osé". La rencontre de mon "âme-sœur" a "été" au rendez-vous… // and how it should look after correction:`], [`tarun" lalwani"`, `tarun” lalwani”`], [`tarun lalwani"`, `tarun lalwani”`], [`"tarun lalwani`,`“tarun lalwani`], [`"tarun" lalwani`,`“tarun” lalwani`], [`"tarun" lalwani"`,`“tarun” lalwani”`], [`"tarun lalwani"`, `“tarun lalwani”`] ] function isCharacterSeparator(value) { return /“, /.test(value) } for ([data, output] of tests) { let qt = "“”" let qtL = '“' let qtR = '”' let bal = 0 let pattern = /["“”]/g let data_new = data while (match = pattern.exec(data)) { if (bal == 0) { if (match.index == 0) { data_new = data_new.replaceAt(match.index, qt[bal]); bal = 1 } else { if (isCharacterSeparator(data_new[match.index-1])) { data_new = data_new.replaceAt(match.index, qtL); } else { data_new = data_new.replaceAt(match.index, qtR); } } } else { if (match.index == data.length - 1) { data_new = data_new.replaceAt(match.index, qtR); } else if (isCharacterSeparator(data_new[match.index-1])) { if (isCharacterSeparator(data_new[match.index+1])) { //previous is separator as well as next one too // "tarun " lalwani" // take a call what needs to be done here? } else { data_new = data_new.replaceAt(match.index, qtL); } } else { if (isCharacterSeparator(data_new[match.index+1])) { data_new = data_new.replaceAt(match.index, qtL); } else { data_new = data_new.replaceAt(match.index, qtR); } } } } console.log(data_new) if (data_new != output) { console.log(`Failed to parse '${data}' Actual='${data_new}' Expected='${output}'`) } ; }