【问题标题】:How to uppercase the first character of a word if it was not preceded or prefixed by a special character sequence?如果单词的第一个字符没有以特殊字符序列开头或前缀,如何将其大写?
【发布时间】:2021-02-16 08:13:06
【问题描述】:

我正在编写 JavaScript 代码。目的是在输入 textarea 时将句号字符 (Hello world. Hi) 之后的每个单词的第一个字符变为大写。

为此,我正在使用以下代码……

$('#div2').on('input', function (evt) {
    var re = /(^|[.!?]\s+)([a-z])/g;
    var box = evt.target;
    var stringStart = box.selectionStart;
    var stringEnd = box.selectionEnd; 
    var val = $(evt.target).val().replace(re, function (m, $1, $2) {
        return $1 + $2.toUpperCase()
    });

    $(evt.target).val(val);
    box.setSelectionRange(stringStart, stringEnd); 
});

按预期工作。 但现在我希望它应该跳过一些像(美国)这样的词。如果在文本中键入单词 U.S.A.,则下一个单词的第一个字符不应为大写。

E.g. 

    U.S.A. is the //Expected  
    U.S.A. Is the //what i am getting (wrong) 

为了实现这一点,我写了下面的代码,但没有按预期工作。

var skipWordUpper = ['U.S.A.', 'Inc.'];
$('#div2').on('input', function (evt) {
    var re = /(^|[.!?]\s+)([a-z])/g;
    var box = evt.target;
    var stringStart = box.selectionStart;
    var stringEnd = box.selectionEnd;

    var str = $('#div2').val();
    var beforeSpace = str.split(" ").splice(-2) 
    var foundPresent = $.inArray(beforeSpace[0], skipWordUpper) > -1; 

    if (!foundPresent) {
        var val = $(evt.target).val().replace(re, function (m, $1, $2) {
            return $1 + $2.toUpperCase()
        });

        $(evt.target).val(val);
        box.setSelectionRange(stringStart, stringEnd);
    } 
});

请任何人帮助找出我所犯的错误并将我置于正确的位置。 或常规 exp 的任何变化。是必须的。 为我对 JAVASCRIPT 的糟糕知识道歉

【问题讨论】:

  • 您是否打算使用缩写白名单,在此之后第一个字符的大写不应该发生。或者您是否假设任何一组单个字符后跟一个点字符是这样的
  • 是的@yunzen,这就是终极目标。
  • 以上哪一项?
  • 是的,我有一组单词后面跟着(。)例如公共汽车。 , Co. 等。后面的词不能大写
  • 所以你在考虑白名单?

标签: javascript regex string replace lookbehind


【解决方案1】:

尝试使用否定的lookbehind来排除正则表达式中的这些词:

$('#div2').on('input', function(evt) {
  var re = /(?<!U.S.A|Inc)([.!?]\s+)([a-z])/g;
  var box = evt.target;
  var stringStart = box.selectionStart;
  var stringEnd = box.selectionEnd;

  var str = $('#div2').val();

  var val = $(evt.target).val().replace(re, function(m, $1, $2) {
    return $1 + $2.toUpperCase()
  });

  $(evt.target).val(val);
  box.setSelectionRange(stringStart, stringEnd);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<textarea id="div2"></textarea>

【讨论】:

    【解决方案2】:

    一种玩法,基于类似的东西,例如...

    /(?&lt;!\b(?:inc|pease|nope|U\.S\.A|u\.s\.w))([.?!]\s+)(\w)/gi

    由于 OP 正在寻找一种 whitelist-blacklist 支持,因此必须采用可靠的方法来清理此类字符串项。正则表达式必须从这样的列表动态构建。因此,在允许正则表达式(搜索)模式的一部分之前,需要对正则表达式特定的控制字符进行转义,然后将其传递给 RegExp 构造函数。

    还请注意,在常用的 JS 引擎中,不完全支持根据MDNcaniuselookbehind assertions,尤其是在将正则表达式的完整语法应用于后视时,如下所示测试用例...

    function toRegExpSearch(str) {
      return String(str)
        .replace((/[$^*+?!:=.|(){}[\]\\]/g), match => `\\${ match }`)
        .replace((/\s+/g), '\\s+');
    }
    
    const regXFirstWordCharAfterFullstop = (/([.?!]\s+)(\w)/g);
    let regXFirstWordCharAfterFullstopException = null;
    
    // please also have a look into ... [https://regex101.com/r/zQ1gzo/1/]
    
    function updateFullstopExceptionRegX(evt) {
      const exceptionPattern = evt.currentTarget.value
        .trim()
        .split(/\s*,\s*|\s+/)
        .map(str => toRegExpSearch(str.replace((/\.$/g), '')))
        .join('|');
    
      regXFirstWordCharAfterFullstopException = (exceptionPattern !== '')
        ? RegExp(`(?<!\\b(?:${ exceptionPattern }))([.?!]\\s+)(\\w)`, 'gi')
        : null;
    
      document
        .querySelector('#regx')
        .textContent = String(regXFirstWordCharAfterFullstopException);
    
      sanitizeText({
        currentTarget: document.querySelector('#text')
      });
    }
    
    function sanitizeText(evt) {
      const textElm = evt.currentTarget;
      const { selectionStart, selectionEnd } = textElm;
    
      textElm.value = (regXFirstWordCharAfterFullstopException === null)
        ? textElm.defaultValue
        : textElm.value
          .replace(
            regXFirstWordCharAfterFullstop,
            (_, $1, $2) => $1 + $2.toLowerCase()
          )
          .replace(
            regXFirstWordCharAfterFullstopException,
            (_, $1, $2) => $1 + $2.toUpperCase()
          );      
      textElm.setSelectionRange(selectionStart, selectionEnd);
    }
    
    function init() {
      document
        .querySelector('#skiplist')
        .addEventListener('input', updateFullstopExceptionRegX);
      document
        .querySelector('#text')
        .addEventListener('input', sanitizeText);
    
      updateFullstopExceptionRegX({
        currentTarget: document.querySelector('#skiplist')
      });
      sanitizeText({
        currentTarget: document.querySelector('#text')
      });
    }
    init();
    input, textarea {
      display: block;
      width: 100%;
      margin: 0;
    }
    pre { margin: 3px 0; padding: 0; }
    <input id='skiplist' type="text" placeholder="... add word or abbreviation to skiplist ..." value="inc. pease, nope, U.S.A. u.s.w." />
    
    <pre><code id="regx">(/(?:)/)</code></pre>
    
    <textarea cols="40" rows="9" id="text" placeholder="...type or paste text freely...">
    U.S.A. Is the country? i want to live in. if you please. yes. nope.
    U.S.A. Is the country? i want to live inc. If you pease. Dope. yes.
    U.S.A. Is the country? i want to live Inc. If you pease. Dope. yes.
    
    u.s.w. And so on. a German abbreviation.
    u.s.w. And so on. a German abbreviation.
    </textarea>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-09-13
      • 1970-01-01
      • 1970-01-01
      • 2010-12-25
      • 1970-01-01
      • 2015-11-28
      相关资源
      最近更新 更多