JavaScript 中字符串匹配的 Switch 语句

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2896626/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 02:22:20  来源:igfitidea点击:

Switch statement for string matching in JavaScript

javascriptregexswitch-statement

提问by Dr. Frankenstein

How do I write a swtich for the following conditional?

如何为以下条件编写开关?

If the url contains"foo", then settings.base_url is "bar".

如果 url包含“foo”,则 settings.base_url 是“bar”。

The following is achieving the effect required but I've a feeling this would be more manageable in a switch:

以下是实现所需的效果,但我觉得这在 switch 中更易于管理:

var doc_location = document.location.href;
var url_strip = new RegExp("http:\/\/.*\/");
var base_url = url_strip.exec(doc_location)
var base_url_string = base_url[0];

//BASE URL CASES

// LOCAL
if (base_url_string.indexOf('xxx.local') > -1) {
    settings = {
        "base_url" : "http://xxx.local/"
    };
}

// DEV
if (base_url_string.indexOf('xxx.dev.yyy.com') > -1) {
    settings = {
        "base_url" : "http://xxx.dev.yyy.com/xxx/"
    };
}

回答by T.J. Crowder

You can't do it in a switchunless you're doing fullstring matching; that's doing substringmatching.(This isn'tquite true, as Sean points out in the comments. See note at the end.)

switch除非您进行完整的字符串匹配,否则您不能在 a 中执行此操作;那是在做子串匹配。正如肖恩在评论中指出的那样,这并不完全正确。请参阅最后的注释。)

If you're happy that your regex at the top is stripping away everything that you don't want to compare in your match, you don't need a substring match, and could do:

如果您很高兴顶部的正则表达式去除了您不想在匹配中进行比较的所有内容,那么您不需要子字符串匹配,并且可以这样做:

switch (base_url_string) {
    case "xxx.local":
        // Blah
        break;
    case "xxx.dev.yyy.com":
        // Blah
        break;
}

...but again, that only works if that's the completestring you're matching. It would fail if base_url_stringwere, say, "yyy.xxx.local" whereas your current code would match that in the "xxx.local" branch.

...但同样,只有当这是您匹配的完整字符串时才有效。如果base_url_string是“yyy.xxx.local”,而您当前的代码将与“xxx.local”分支中的代码匹配,则会失败。



Update: Okay, so technically you canuse a switchfor substring matching, but I wouldn't recommend it in most situations. Here's how (live example):

更新:好的,所以从技术上讲,您可以使用 aswitch进行子字符串匹配,但在大多数情况下我不推荐它。方法如下(现场示例):

function test(str) {
    switch (true) {
      case /xyz/.test(str):
        display("? Matched 'xyz' test");
        break;
      case /test/.test(str):
        display("? Matched 'test' test");
        break;
      case /ing/.test(str):
        display("? Matched 'ing' test");
        break;
      default:
        display("? Didn't match any test");
        break;
    }
}

That works because of the way JavaScript switchstatements work, in particular two key aspects: First, that the cases are considered in source textorder, and second that the selector expressions (the bits after the keyword case) are expressionsthat are evaluated as that case is evaluated (not constants as in some other languages). So since our test expression is true, the first caseexpression that results in truewill be the one that gets used.

这是因为 JavaScriptswitch语句的工作方式,特别是两个关键方面:首先,按源文本顺序考虑 case ,其次,选择器表达式(关键字之后的位case)是作为 case 被评估的表达式评估(不像其他一些语言那样是常量)。因此,由于我们的测试表达式是true,产生的第一个case表达式true将是被使用的表达式。

回答by Steven Pribilinskiy

RegExp can be used on the input string not just technically but practically with the matchmethod too.

RegExp 不仅可以在技术上用于输入字符串,而且在实际中也可以用于该match方法。

Because the output of the match()is an array we need to retrieve the first array element of the result. When the match fails, the function returns null. To avoid an exception error we will add the ||conditional operator before accessing the first array element and test against the inputproperty that is a static property of regular expressionsthat contains the input string.

因为 的输出match()是一个数组,所以我们需要检索结果的第一个数组元素。当匹配失败时,函数返回null。为了避免出现异常错误,我们将添加||访问针对第一个数组元素和测试之前,条件运算input性能是正则表达式的静态属性包含输入字符串。

str = 'XYZ test';
switch (str) {
  case (str.match(/^xyz/) || {}).input:
    console.log("Matched a string that starts with 'xyz'");
    break;
  case (str.match(/test/) || {}).input:
    console.log("Matched the 'test' substring");        
    break;
  default:
    console.log("Didn't match");
    break;
}

Another approach is to use the String()constructor to convert the resulting array that must have only 1 element (no capturing groups) and whole string must be captured with quanitifiers (.*) to a string. In case of a failure the nullobject will become a "null"string. Not convenient.

另一种方法是使用String()构造函数将必须只有 1 个元素(没有捕获组)并且必须使用限定符 ( .*)捕获整个字符串的结果数组转换为字符串。在失败的情况下,null对象将变成一个"null"字符串。不方便。

str = 'haystack';
switch (str) {
  case String(str.match(/^hay.*/)):
    console.log("Matched a string that starts with 'hay'");
    break;
}

Anyway, a more elegant solution is to use the /^find-this-in/.test(str)with switch (true)method which simply returns a boolean value and it's easier to search without case sensitivity.

无论如何,一个更优雅的解决方案是使用/^find-this-in/.test(str)withswitch (true)方法,它只返回一个布尔值,并且在不区分大小写的情况下更容易搜索。

回答by Sean Kinsey

Just use the location.host property

只需使用 location.host 属性

switch (location.host) {
    case "xxx.local":
        settings = ...
        break;
    case "xxx.dev.yyy.com":
        settings = ...
        break;
}

回答by Mitar

Another option is to use inputfield of a regexp match result:

另一种选择是使用正则表达式匹配结果的input字段:

str = 'XYZ test';
switch (str) {
  case (str.match(/^xyz/) || {}).input:
    console.log("Matched a string that starts with 'xyz'");
    break;
  case (str.match(/test/) || {}).input:
    console.log("Matched the 'test' substring");        
    break;
  default:
    console.log("Didn't match");
    break;
}

回答by James

var token = 'spo';

switch(token){
    case ( (token.match(/spo/) )? token : undefined ) :
       console.log('MATCHED')    
    break;;
    default:
       console.log('NO MATCH')
    break;;
}


--> If the match is made the ternary expression returns the original token
----> The original token is evaluated by case


--> 如果匹配,则三元表达式返回原始标记
----> 原始标记按大小写计算

--> If the match is not made the ternary returns undefined
----> Case evaluates the token against undefined which hopefully your token is not.

--> 如果不匹配,则三元返回 undefined
----> Case 根据 undefined 评估令牌,希望您的令牌不是。

The ternary test can be anything for instance in your case

例如在您的情况下,三元测试可以是任何东西

( !!~ base_url_string.indexOf('xxx.dev.yyy.com') )? xxx.dev.yyy.com : undefined 

===========================================

============================================

(token.match(/spo/) )? token : undefined ) 

is a ternary expression.

是一个三元表达式。

The test in this case is token.match(/spo/) which states the match the string held in token against the regex expression /spo/ ( which is the literal string spo in this case ).

这种情况下的测试是 token.match(/spo/) ,它说明 token 中保存的字符串与正则表达式 /spo/ (在这种情况下是文字字符串 spo )的匹配。

If the expression and the string match it results in true and returns token ( which is the string the switch statement is operating on ).

如果表达式和字符串匹配,则结果为 true 并返回标记(即 switch 语句正在操作的字符串)。

Obviously token === token so the switch statement is matched and the case evaluated

显然 token === token 所以 switch 语句被匹配并且 case 被评估

It is easier to understand if you look at it in layers and understand that the turnery test is evaluated "BEFORE" the switch statement so that the switch statement only sees the results of the test.

如果您分层查看它并理解 Turnery 测试是在“BEFORE”switch 语句之前评估的,则更容易理解,以便 switch 语句只看到测试的结果。

回答by Geery.S

It may be easier. Try to think like this:

可能会更容易。试着这样想:

  • first catch a string between regular characters
  • after that find "case"
  • 首先在常规字符之间捕获一个字符串
  • 之后找到“案例”

:

// 'www.dev.yyy.com'
// 'xxx.foo.pl'

var url = "xxx.foo.pl";

switch (url.match(/\..*.\./)[0]){
   case ".dev.yyy." :
          console.log("xxx.dev.yyy.com");break;

   case ".some.":
          console.log("xxx.foo.pl");break;
} //end switch

回答by TacB0sS

Might be too late and all, but I liked this in case assignment :)

可能为时已晚,但我喜欢这个以防万一:)

function extractParameters(args) {
    function getCase(arg, key) {
        return arg.match(new RegExp(`${key}=(.*)`)) || {};
    }

    args.forEach((arg) => {
        console.log("arg: " + arg);
        let match;
        switch (arg) {
            case (match = getCase(arg, "--user")).input:
            case (match = getCase(arg, "-u")).input:
                userName = match[1];
                break;

            case (match = getCase(arg, "--password")).input:
            case (match = getCase(arg, "-p")).input:
                password = match[1];
                break;

            case (match = getCase(arg, "--branch")).input:
            case (match = getCase(arg, "-b")).input:
                branch = match[1];
                break;
        }
    });
};

you could event take it further, and pass a list of option and handle the regex with |

你可以更进一步,并传递一个选项列表并使用 | 处理正则表达式。