【问题标题】:Make a string lowercase respecting quotes - Javascript使字符串小写尊重引号 - Javascript
【发布时间】:2015-09-13 16:05:41
【问题描述】:

我正在为 Domain Specific Language,(或 DSL)构建解析器,并且我正在尝试将字符串转换为全小写。我知道toLowerCase 可以轻松完成这项任务,但我需要在原始情况下保留用双引号或单引号("')引用的字符串。举例如下:

输入: ThIs iS a teST "sTriNg Y'alL" aS yOu cAN sEE 'hEllO woRl\' o miNE'

输出: this is a test "sTriNg Y'alL" as you can see 'hEllO woRl\' o miNE'

编辑:添加反斜杠引号

【问题讨论】:

  • 你需要写一个解析器。没有任何内置功能可以为您做到这一点。
  • 我收集到了,我正在寻找有关最快和最干净的方法的建议。

标签: javascript string case quotes lowercase


【解决方案1】:

刚刚组装了一个快速解析器,不确定它的工作情况如何,但它应该可以处理无限的反斜杠转义

function string_to_block(str) {
    var blocks = [],
        i, j, k;
    function isEscaped(str, i) {
        var escaped = false;
        while (str[--i] === '\\') escaped = !escaped;
        return escaped;
    }
    start: for (i = 0; i < str.length; i = j + 1) {
        find: for (j = i; j < str.length; ++j) {
            if (str[j] === '"' && !isEscaped(str, j)) {
                if (j > i) {
                    blocks.push({type: 'regular', str: str.slice(i, j)});
                }
                end: for (k = j + 1; k < str.length; ++k) {
                    if (str[k] === '"' && !isEscaped(str, k)) {
                        // found a "str" block
                        blocks.push({type: 'quote', str: str.slice(j, k + 1)});
                        j = k;
                        break find;
                    }
                }
                throw new SyntaxError('unclosed "str... starting at index ' + j);
            }
            if (str[j] === "'" && !isEscaped(str, j)) {
                if (j > i) {
                    blocks.push({type: 'regular', str: str.slice(i, j)});
                }
                end: for (k = j + 1; k < str.length; ++k) {
                    if (str[k] === "'" && !isEscaped(str, k)) {
                        // found a 'str' block
                        blocks.push({type: 'quote', str: str.slice(j, k + 1)});
                        j = k;
                        break find;
                    }
                }
                throw new SyntaxError("unclosed 'str... starting at index " + j);
            }
        }
    }
    if (k + 1 < str.length) {
        blocks.push({type: 'regular', str: str.slice(k + 1)});
    }
    return blocks;
}

现在

var foo = string_to_block("ThIs iS a teST \"sTriNg Y'alL\" aS yOu cAN sEE 'hEllO woRl\\' o miNE'");
/*
[
    {"type": "regular", "str": "ThIs iS a teST "},
    {"type": "quote"  , "str": "\"sTriNg Y'alL\""},
    {"type": "regular", "str": " aS yOu cAN sEE "},
    {"type": "quote"  , "str": "'hEllO woRl\\' o miNE'"}
]
*/

所以我们可以根据需要重新构建您的字符串;

var i, str = '';
for (i = 0; i < foo.length; ++i) {
    if (foo[i].type === 'regular') str += foo[i].str.toLowerCase();
    else str += foo[i].str;
}
str; // this is a test "sTriNg Y'alL" as you can see 'hEllO woRl\' o miNE'

【讨论】:

  • 这实际上超出了我的要求,它完全符合我的要求,还有更多!有一个小问题。此测试字符串:"ThIs iS a teST \"sTriNg Y'alL\" aS yOu cAN sEE 'hEllO woRl\\' o miNE'" 和此测试字符串:"ThIs iS a teST \"sTriNg Y'alL\" aS yOu cAN sEE 'hEllO woRl\\' o miNE'" test StrING 不相同,但它们都生成相同的结果。如果你能解决这个问题,那就太棒了!
  • @SamWeaver 我猜你的意思是最后一部分,如果不是报价的一部分,就会丢失。我想我在最后检查了错误的变量,请尝试新的编辑并告诉我。
  • 这在没有预设引用块时不起作用。在这种情况下,它返回一个空字符串。我正在研究如何解决。
【解决方案2】:

我确信有一个正则表达式解决方案,但这是另一种解决方案,它在将带引号的字符串小写之前替换它:

String.prototype.toLowerCaseQuoted = function() {
   var str = this.valueOf();
   var replacements = [];
   var I = 0;
   str = str
      .replace(/((\".+\")|(\'.+\'))/g, function(s) {
         console.log(s)
         replacements.push(s);
         return "%s"+(I++)+"%"
      })
      .toLowerCase()
      .replace(/%s([0-9]+)%/g, function(s) {
         var k = parseInt(s.match(/([0-9])+/)[0]);
         console.log(k)
         return replacements[k];
      });
   return str;
}

例如:

"WILL BE LOWER CASE \"QUOTED\" \'MORE QUOTED\'".toLowerCaseQuoted()

返回 "will be lower case "QUOTED" 'MORE QUOTED'"

【讨论】:

  • 这不能处理转义引号"WILL BE \\\"LOWER\\\" CASE \"QUOTED\" \'MORE QUOTED\'".toLowerCaseQuoted(); // "will be \"LOWER\" CASE "QUOTED" 'MORE QUOTED'"
【解决方案3】:

这是@Paul S 的后续。它应该处理不带引号的字符串...

function string_to_block(str) {
    var blocks = [],
        i, j, k;
    function isEscaped(str, i) {
        var escaped = false;
        while (str[--i] === '\\') escaped = !escaped;
        return escaped;
    }
    start: for (i = 0; i < str.length; i = j + 1) {
        find: for (j = i; j <= str.length; ++j) {
            if (str[j] === '"' && !isEscaped(str, j)) {
                if (j > i) {
                    blocks.push({type: 'regular', str: str.slice(i, j)});
                }
                end: for (k = j + 1; k < str.length; ++k) {
                    if (str[k] === '"' && !isEscaped(str, k)) {
                        // found a "str" block
                        blocks.push({type: 'quote', str: str.slice(j, k + 1)});
                        j = k;
                        break find;
                    }
                }
                throw new SyntaxError('unclosed "str... starting at index ' + j);
            }
            if (str[j] === "'" && !isEscaped(str, j)) {
                if (j > i) {
                    blocks.push({type: 'regular', str: str.slice(i, j)});
                }
                end: for (k = j + 1; k < str.length; ++k) {
                    if (str[k] === "'" && !isEscaped(str, k)) {
                        // found a 'str' block
                        blocks.push({type: 'quote', str: str.slice(j, k + 1)});
                        j = k;
                        break find;
                    }
                }
                throw new SyntaxError("unclosed 'str... starting at index " + j);
            }
            if (j === str.length) {
                            // We reached the end without finding any quote blocks
              if (j > i) {
                blocks.push({type: 'regular', str: str.slice(i,j)});
              }
            }
        }
    }
    return blocks;
}

【讨论】:

    【解决方案4】:
    String.prototype.toLowerCaseQuoted = function() {
        var oldValue = this.valueOf();
        var newValue = '';
        var inside = 0;
    
        for (var i = 0; i < oldValue.length; i++) {
            if (oldValue[i] == '"') {
                if (inside == 0) {
                    inside = 1;
                } else {
                    inside = 0;
                }
            }
    
            if (inside == 1) {
                newValue += oldValue[i];
            } else {
                newValue += oldValue[i].toLowerCase();
            }
        }
    
        return newValue;
     }
    

    【讨论】:

    • 这会处理双引号,但无法正确处理单引号。
    猜你喜欢
    • 1970-01-01
    • 2013-05-18
    • 2019-11-09
    • 2016-09-19
    • 2011-12-26
    • 1970-01-01
    • 1970-01-01
    • 2014-05-20
    • 2017-08-29
    相关资源
    最近更新 更多