用引号替换双引号

Tak*_*Isy 15 javascript regex jquery

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

这个想法

这里有一个简要说明原则的片段:
对于引号,"正确"的引号有开启和关闭,因此需要以良好的方式进行替换.

$('#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, '” ');
});
Run Code Online (Sandbox Code Playgroud)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea id="myInput"></textarea>
Run Code Online (Sandbox Code Playgroud)

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

例子

可能的输入(小心,法语里面!:)):
⋅我很开心!Ç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应"不应被替换".
⋅我说:"如果它也适用于'单身',我会更喜欢它!"

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

需要

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

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

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

任何想法将不胜感激.

Tak*_*Isy 1

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

\n\n

\\b请记住,我的主要问题是由于重音字符而无法使用。
\n我能够通过使用本主题中的解决方案来解决这个问题:
\ nRemoveaccents/diacritics in a string in JavaScript

\n\n

之后,我使用了一个修改后的函数,该函数深受此处答案的启发\xe2\x80\xa6
\n如何替换 JavaScript 中特定索引处的字符?

\n\n

\xe2\x80\xa6 并度过了一段非常艰难的时期,玩了很多 RegEx 最终得到了这个解决方案:

\n\n

\r\n
\r\n
var str_orig = `\xc2\xb7 I\'m "happy" ! \xc3\x87a y est, j\'ai "os\xc3\xa9", et mon "\xc3\xa2me s\xc5\x93ur" \xc3\xa9tait au rendez-vous\xe2\x80\xa6\r\n\xc2\xb7 The sign says: "Some text "some text" some text." and "Note the space here !"\r\n\xe2\x8b\x85 "Inc"or"rect" quo"tes should " not be replaced.\r\n\xc2\xb7 I said: "If it works on \'singles\' too, I\'d love it even more!"\r\nword1" word2"\r\nword1 word2"\r\n"word1 word2\r\n"word1" word2\r\n"word1" word2"\r\n"word1 word2"`;\r\n\r\n// Thanks, exactly what I needed!\r\nvar str_norm = str_orig.normalize(\'NFD\').replace(/[\\u0300-\\u036f]/g, \'\');\r\n\r\n// Thanks for inspiration\r\nString.prototype.replaceQuoteAt = function(index, shift) {\r\n  const replacers = "\xe2\x80\x9c\xe2\x80\x98\xe2\x80\x9d\xe2\x80\x99";\r\n  var offset = 1 * (this[index] == "\'") + 2 * (shift);\r\n  return this.substr(0, index) + replacers[offset] + this.substr(index + 1);\r\n}\r\n\r\n// Opening quote: not after a boundary, not before a space or at the end\r\nvar re_start = /(?!\\b)["\'](?!(\\s|$))/gi;\r\nwhile ((match = re_start.exec(str_norm)) != null) {\r\n  str_orig = str_orig.replaceQuoteAt(match.index, false);\r\n}\r\n\r\n// Closing quote: not at the beginning or after a space, not before a boundary\r\nvar re_end = /(?<!(^|\\s))["\'](?!\\b)/gi;\r\nwhile ((match = re_end.exec(str_norm)) != null) {\r\n  str_orig = str_orig.replaceQuoteAt(match.index, true);\r\n}\r\n\r\nconsole.log("Corrected: \\n", str_orig);
Run Code Online (Sandbox Code Playgroud)\r\n
\r\n
\r\n

\n\n

下面是一个带有textarea.
\n我刚刚创建了第一个代码片段的代码函数,并且我在插入符号位置周围使用子字符串来过滤函数的调用(避免在每个字符输入上调用它):

\n\n

\r\n
\r\n
String.prototype.replaceQuoteAt = function(index, offset) {\r\n  const replacers = "\xe2\x80\x9c\xe2\x80\x98\xe2\x80\x9d\xe2\x80\x99";\r\n  var i = 2 * (offset) + 1 * (this[index] == "\'");\r\n  return this.substr(0, index) + replacers[i] + this.substr(index + 1);\r\n}\r\n\r\nfunction replaceQuotes(str) {\r\n  var str_norm = str.normalize(\'NFD\').replace(/[\\u0300-\\u036f]/g, \'\');\r\n  var re_quote_start = /(?!\\b)["\'](?!(\\s|$))/gi;\r\n  while ((match = re_quote_start.exec(str_norm)) != null) {\r\n    str = str.replaceQuoteAt(match.index, false);\r\n  }\r\n  var re_quote_end = /(?<!(^|\\s))["\'](?!\\b)./gi;\r\n  while ((match = re_quote_end.exec(str_norm)) != null) {\r\n    str = str.replaceQuoteAt(match.index, true);\r\n  }\r\n  return str;\r\n}\r\n\r\nvar pasted = 0;\r\ndocument.getElementById("myInput").onpaste = function(e) {\r\n  pasted = 1;\r\n}\r\n\r\ndocument.getElementById("myInput").oninput = function(e) {\r\n  var caretPos = this.selectionStart; // Gets caret position\r\n  var chars = this.value.substring(caretPos - 2, caretPos + 1); // Gets 2 chars before caret (just typed and the one before), and 1 char just after\r\n  if (pasted || chars.includes(`"`) || chars.includes(`\'`)) { // Filters the calling of the function\r\n    this.value = replaceQuotes(this.value); // Calls the function\r\n    if (pasted) {\r\n      pasted = 0;\r\n    } else {\r\n      this.setSelectionRange(caretPos, caretPos); // Restores caret position\r\n    }\r\n  }\r\n}
Run Code Online (Sandbox Code Playgroud)\r\n
#myInput {\r\n  width: 90%;\r\n  height: 100px;\r\n}
Run Code Online (Sandbox Code Playgroud)\r\n
<textarea id="myInput"></textarea>
Run Code Online (Sandbox Code Playgroud)\r\n
\r\n
\r\n

\n\n

它似乎符合我现在能想象的一切。
\n该函数在以下情况下正确替换引号:
\n\xe2\x8b\x85 定期键入、
\n\xe2\x8b\x85 在键入文本后添加引号、
\n\xe2\x8b\x85 粘贴文本。

\n\n

它取代了双引号和单引号。

\n\n

无论如何,由于我根本不是正则表达式专家,如果您发现可能不需要的行为或改进表达式的方法,请随时发表评论。

\n