JavaScript 中字符串匹配的 Switch 语句

IT技术 javascript regex switch-statement
2021-02-11 14:14:46

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

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

以下是实现所需的效果,但我感觉这在 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/"
    };
}
6个回答

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

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

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

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


更新:好的,所以从技术上讲,您可以使用 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;
    }
}

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

RegExp 也可以用于该match方法的输入字符串

为确保我们在case子句中有匹配项,我们将针对 success 的属性测试原始str值(提供给switch语句)inputmatch

input包含原始输入字符串的正则表达式的静态属性

如果match失败则返回null为了避免异常错误,我们||在访问input属性之前使用可选链运算符(或传统 ES 中的逻辑条件运算符)

const 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;
}

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

const str = 'XYZ test';

switch (str.toLowerCase()) {
  case String(str.match(/^xyz.*/i)):
    console.log("Matched a string without case sensitivity");
    break;
  case String(str.match(/.*tes.*/)):
    console.log("Matched a string using a substring 'tes'");
    break;
}

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

const str = 'haystack';

switch (true) {
  case /^hay.*/.test(str):
    console.log("Matched a string that starts with 'hay'");
    break;
}
pribilinsiky:您可能应该提到您的第三个解决方案(使用 test())要求您拥有 switch(true)。
2021-04-12 14:14:46

只需使用 location.host 属性

switch (location.host) {
    case "xxx.local":
        settings = ...
        break;
    case "xxx.dev.yyy.com":
        settings = ...
        break;
}
谢谢,+1 因为这是我真正应该做的
2021-04-12 14:14:46
您必须注意传递给 switch 语句的变量类型。必须是一个字符串。确保你能做到switch ("" + location.host)
2021-04-12 14:14:46

另一种选择是使用正则表达式匹配结果的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;
}
好东西。在这种情况下,任何数组属性也可以用于测试,例如.length:
2021-03-31 14:14:46
var token = 'spo';

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


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

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

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

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

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

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

是一个三元表达式。

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

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

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

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

好的,现在我明白了。我很困惑,因为很明显这token.match(/spo/)会匹配。
2021-03-26 14:14:46
你的回答令人困惑。你能回顾和改进这个例子和解释吗?
2021-03-27 14:14:46
@falsarella 我解释了我认为你理解困难的部分。我不认为我可以举一个更简单的例子。如果您有更多问题或可以更具体地解决您的困难,我可以提供更多帮助。
2021-04-11 14:14:46