javascript 특수문자 큰 따옴표를 따옴표로 바꾸십시오.




쿼리 큰 따옴표 (3)

마침내 모든 필요를 충족시키는 솔루션이 있습니다.
나는 그것이 단순한 경우에 완벽 할 수있는 TJ의 것보다 훨씬 더 복잡하다는 것을 인정한다.

필자의 주요 문제는 악센트 부호가있는 문자 때문에 \b 를 사용하는 것이 불가능하다는 점을 기억하십시오.
이 주제의 솔루션을 사용하여이 문제를 해결할 수있었습니다.
JavaScript에서 문자열의 악센트 / 발음 구별 기호 제거

그 후, 나는 그 대답에서 영감을 얻은 수정 된 함수를 사용했다.
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 = /(?<!(^|\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 이있는 작업 예제의 일부입니다.
방금 첫 번째 스 니펫의 코드 함수를 만들었고 캐럿 위치 주변의 하위 문자열을 사용하여 모든 문자 입력에서 함수 호출을 피하는 함수 호출을 필터링했습니다.

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>

지금 당장 상상할 수있는 것만으로도 효과가있는 것 같습니다.
이 함수는 다음과 같은 경우 따옴표를 바꿉니다.
∙ 정기적으로 타이핑하고,
∙ 텍스트를 입력 한 후 따옴표를 추가합니다.
∙ 텍스트 붙여 넣기.

이중 따옴표와 단락 따옴표를 모두 대체합니다.

어쨌든 RegEx 전문가가 아니기 때문에 원하지 않는 행동이나 표현을 개선 할 수있는 방법을 느낀다면 자유롭게 의견을 말하십시오.

인용 부호를 사용자 입력에서 "수정 된"인용 부호로 바꾸는 방법을 찾고 있습니다.

아이디어

다음은 원칙을 간략하게 보여주는 스 니펫입니다.
따옴표의 경우 "올바른"문구는 "닫는 문구 를 가지므로 좋은 방법으로 바꿔야합니다.

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

그러나 위의 모든 경우에 작동하지 않습니다.
예를 들어, "quoted word"가 문장이나 줄의 맨 처음이나 끝에있을 때.

예제들

가능한 입력 (조심하십시오!) :
⋅ 나는 행복하다! Ça y est, j'ai "osé", et mon "âme sœur"était au rendez-vous ...
⋅ 기호는 "일부 텍스트"일부 텍스트 "일부 텍스트"라고 표시합니다. 여기에 공간을 적어 두십시오! "
∙ "Inc"또는 "rect"quo "tes should"는 대체되지 않아야합니다.
⋅ 나는 말했다 : "싱글에서도 효과가 있다면 더 좋아할 것"이라고 말했다.

올바른 출력 :
⋅ 나는 행복하다! Ça y est, j'ai "osé", et mon "âme sœur"était au rendez-vous ...
⋅ 기호는 "일부 텍스트"일부 텍스트 "일부 텍스트"및 "여기에 공간 참고!"라고 표시되어 있습니다.
∙ "Inc"또는 "rect"quo "tes should"는 대체되지 않아야합니다.
⋅ 나는 말했다 : "싱글에서도 효과가 있다면 더 좋아할 것"이라고 말했다.

잘못된 출력 :
⋅ 기호는 "일부 텍스트"일부 텍스트 "일부 텍스트"및 [...]
왜 그것이 틀린가 :
→ 따옴표의 끝과 닫는 표시 사이에는 공백이 없어야합니다.
→ 닫는 인용 부호와 단어 사이에 공백이 있어야합니다.
→ 단어와 시작 인용 부호 사이에는 공백이 있어야합니다.
→ 시작 인용 부호와 인용 부호 사이에는 공백이 없어야합니다.

필요성

어떻게 모든 경우에 인용 부호를 효과적이고 쉽게 대체 할 수 있습니까?
가능하다면 전체 문장을 타이핑 한 후에도 따옴표를 "수정"할 수있는 솔루션을 원합니다.

유감스럽게도 "é"나 "ü"와 같은 악센트 부호가있는 문자는 불행히도 단어 분리로 취급되기 때문에 정규 표현식에서 "\ b"라는 단어 구분 기호를 사용할 수 없다는 것을 유의하십시오. (출처 : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions )

물론 다른 해결책이 없다면 단어 분리 문자로 간주하고 정규 표현식에서 사용하는 목록을 작성하겠습니다. 하지만 나는 목록이 아닌 훌륭한 기능을 원한다.

어떤 아이디어라도 감사 할 것입니다.


"단어"가 문장이나 줄의 맨 처음이나 맨 끝에 오는 경우를 제외하고는 많은 경우에 대해 작동합니다.

이 문제를 해결하기 위해 라인 어설 션의 시작 / 끝과 공간을 교대로 사용하여이를 포착하여 교체에 사용할 수 있습니다.

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

교대는 ^| / $| . 캡쳐 그룹은 어설 션과 일치하면 " " , 실패하면 일치합니다.

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

그러나 사용자 입력에서 "이스케이프"문자를 피하기를 원한다고 말한 것입니다. 나는 당신이 그것을 사용하려고 계획하고 있는지 모르겠다. 그러나 위와 같은 것은 거의 그런 종류의 설명을 가진 문제에 사용하는 접근법이 아니다.


그래서 regex replace 접근법을 따르는 대신에, 따옴표로 균형을 잡는 간단한 루핑을 사용할 것입니다. 나타나는 모든 작은 따옴표가 다른 따옴표와 일치한다고 가정하면 쌍 따옴표로 바뀝니다.

다음은 같은 테스트 구현입니다.

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}'`)
} ;
}

업데이트 -1 : 2018 년 4 월 20 일

기능을 업데이트했습니다. 가장자리 경우가있을 수 있지만 테스트에 모든 것을 넣고 실행하고 예상대로 작동하지 않는 문제를 수정해야합니다.





regex