且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

用引号替换双引号

更新时间:2023-02-23 12:58:31

我得到了一个最终满足我所有需求的解决方案。

我承认它比TJ的复杂得多,这对于简单来说非常完美案例。

I got a solution that finally fits all my needs.
I admit it is a lot more complicated than T.J.'s one, which can be perfect for simple cases.

请记住,我的主要问题是使用 \b 因为带有重音符号而无法使用。
我能够通过使用本主题的解决方案摆脱这个问题:

在JavaScript中删除字符串中的重音符号/变音符号

Remember, my main problem was the impossilibity to use \b because of the accented characters.
I was able to get rid of that issue by using the solution from this topic:
Remove accents/diacritics in a string in JavaScript

之后,我使用了修改后的函数从这里的答案中获得了很大的启发...

如何在JavaScript中替换特定索引处的字符?

After that, I used a modified function highly inspired from the answer here…
How do I replace a character at a particular index in JavaScript?

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

… and had a very hard time, playing a lot with RegEx to finally get to that solution:

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 = /(?<!(^|\s))["'](?!\b)/gi;
while ((match = re_end.exec(str_norm)) != null) {
  str_orig = str_orig.replaceQuoteAt(match.index, true);
}

console.log("Corrected: \n", str_orig);

以下是一个带有 textarea 的工作示例的片段。

我刚刚创建了第一个代码段的代码函数,我在插入符号位置使用子字符串来过滤函数的调用(避免在每个字符输入上调用它) :

And below is a snippet of a working example with a textarea.
I've just created a function of the code of the first snippet, and I'm using a substring around the caret position to filter the calling of the function (that avoids calling it on every character input):

String.prototype.replaceQuoteAt = function(index, offset) {
  const replacers = ""‘"’";
  var i = 2 * (offset) + 1 * (this[index] == "'");
  return this.substr(0, index) + replacers[i] + this.substr(index + 1);
}

function replaceQuotes(str) {
  var str_norm = str.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
  var re_quote_start = /(?!\b)["'](?!(\s|$))/gi;
  while ((match = re_quote_start.exec(str_norm)) != null) {
    str = str.replaceQuoteAt(match.index, false);
  }
  var re_quote_end = /(?<!(^|\s))["'](?!\b)./gi;
  while ((match = re_quote_end.exec(str_norm)) != null) {
    str = str.replaceQuoteAt(match.index, true);
  }
  return str;
}

var pasted = 0;
document.getElementById("myInput").onpaste = function(e) {
  pasted = 1;
}

document.getElementById("myInput").oninput = function(e) {
  var caretPos = this.selectionStart; // Gets caret position
  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
  if (pasted || chars.includes(`"`) || chars.includes(`'`)) { // Filters the calling of the function
    this.value = replaceQuotes(this.value); // Calls the function
    if (pasted) {
      pasted = 0;
    } else {
      this.setSelectionRange(caretPos, caretPos); // Restores caret position
    }
  }
}

#myInput {
  width: 90%;
  height: 100px;
}

<textarea id="myInput"></textarea>

它似乎适用于我能想象的所有权利现在。

函数在以下情况下正确替换引号:
$ b $b⋅定期输入,
$ b $b⋅在输入文本后添加引号,

⋅粘贴文本。

It seems to work with all I can imagine right now.
The function correctly replaces the quotes when:
⋅ typing regularly,
⋅ adding quotes after we typed the text,
⋅ pasting text.

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

It replaces both the double and the singles quotes.

无论如何,因为我是ñ如果您注意到可能不需要的行为或改善表达方式,请随时注释RegEx专家。

Anyway, as I am not a RegEx expert at all, please feel free to comment if you notice a behaviour that may be unwanted, or a way to improve the expressions.