在JavaScript中切换字符串匹配的语句

时间:2010-05-24 11:33:19

标签: javascript regex switch-statement

如何为以下条件写一个swtich?

如果网址包含“foo”,则settings.base_url为“bar”。

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

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/"
    };
}

9 个答案:

答案 0 :(得分:323)

除非您正在进行完整字符串匹配,否则无法在switch中执行此操作;正在进行 substring 匹配。 (这不是非常正如Sean在评论中指出的那样。请参阅最后的注释。)< / em>的

如果你很高兴你的顶级正则表达式剥离了你不想在比赛中比较的所有东西,你不需要子串匹配,并且可以这样做:

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

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


更新:好的,从技术上讲,可以使用switch进行子字符串匹配,但在大多数情况下我不建议这样做。这是(live example):

的方法
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;
    }
}

这是因为JavaScript switch statements work的方式,特别是两个关键方面:首先,案例以源文本顺序考虑,其次是选择器表达式(位)在关键字case)之后是表达式,在评估该情况时评估它们(不像其他语言中的常量)。因此,由于我们的测试表达式为true,因此导致case的第一个true表达式将被使用。

答案 1 :(得分:48)

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

因为match()的输出是一个数组,我们需要检索结果的第一个数组元素。当匹配失败时,函数返回null。为了避免异常错误,我们将在访问第一个数组元素之前添加||条件运算符,并针对包含输入字符串的input属性that is a static property of regular expressions进行测试。

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个元素(没有捕获组)的结果数组,并且必须使用quanitifiers(.*)将整个字符串捕获到字符串。如果失败,null对象将变为"null"字符串。不方便。

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

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

答案 2 :(得分:34)

只需使用location.host属性

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

答案 3 :(得分:12)

另一种选择是使用regexp match resultinput字段:

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

答案 4 :(得分:3)

var token = 'spo';

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


- &GT;如果匹配,则三元表达式返回原始标记
----&GT;原始令牌按案例

评估

- &GT;如果没有匹配,则三元返回undefined
----&GT; Case根据undefined评估令牌,希望你的令牌不是。

三元测试可以是例如你的情况

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

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

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

ternary expression.

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

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

显然令牌===令牌,所以switch语句匹配并且案例评估

如果你在图层中查看并理解turnery测试是在“语句前”评估,以便switch语句只能看到测试结果,那么更容易理解。

答案 5 :(得分:3)

可能更容易。试着这样思考:

  • 首先捕捉常规字符之间的字符串
  • 之后找到&#34; case&#34;

// '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

答案 6 :(得分:1)

可能为时已晚,但在案例分配中我喜欢这个:)

 public ActionResult _LoadItemOnDate(string date)
    {
        var dt = DateTime.ParseExact(date, "dd/MM/yyyy",
                                   System.Globalization.CultureInfo.InvariantCulture);
        bool Working = true;
        var custmenuheadList = _customermenuH.findbyDate(dt).GroupBy(x => x.CustMenu_OrderId).Select(x => x.First());
        List<CustomerViewModel> CustomerList = new List<CustomerViewModel>();

        if (dt.DayOfWeek.ToString() == "Friday" || dt.DayOfWeek.ToString() == "Saturday")
        {
            Working = false;
        }
        var address = _custaddress.FindbyId(0);
        foreach (var item in custmenuheadList)
        {
            var CustomerOrder = _custOrder.FindbyId(Convert.ToInt64(item.CustMenu_OrderId));
            if(CustomerOrder.CustOrdr_Count == 0 || CustomerOrder.CustOrdr_Count == null)
            {
                CustomerOrder.CustOrdr_Count = 1;
            }
            if(CustomerOrder.IsPaid != null)
            {
                for (int i = 0; i < CustomerOrder.CustOrdr_Count; i++)
                {
                    var customer = _customer.FindbyId(Convert.ToInt64(item.CustMenu_CustID));
                    if (Working != true)
                    {
                        address = _custaddress.FindbyId(Convert.ToInt64(CustomerOrder.DelvryAddr_Weekend));
                    }
                    else
                    {
                        address = _custaddress.FindbyId(Convert.ToInt64(CustomerOrder.DelvryAddr_Working));
                    }
                    CustomerViewModel cvmobj = new CustomerViewModel();
                    cvmobj.CustName = customer.CustName;
                    cvmobj.CustPhone = customer.CustPhone;
                    if (address != null)
                    {
                        cvmobj.CustAddr1 = address.CustAddr1;
                        cvmobj.CustAddr2 = address.CustAddr2;

                        var city = _city.FindbyId(Convert.ToInt64(address.CustAddrCityID));
                        var State = _state.FindbyId(Convert.ToInt64(address.CustAddrStateID));
                        if (city != null)
                        {
                            cvmobj.CityName = city.Name;
                        }
                        if (State != null)
                        {
                            cvmobj.StateName = State.StateName;
                        }
                    }
                    CustomerList.Add(cvmobj);
                }
            }
        }
        return View(CustomerList);
    }

你可以将事件进一步发展,并传递一个选项列表并使用|

处理正则表达式

答案 7 :(得分:0)

独立版本,可提高工作安全性:

switch((s.match(r)||[null])[0])

function identifyCountry(hostname,only_gov=false){
    const exceptionRe = /^(?:uk|ac|eu)$/ ; //https://en.wikipedia.org/wiki/Country_code_top-level_domain#ASCII_ccTLDs_not_in_ISO_3166-1
    const h = hostname.split('.');
    const len = h.length;
    const tld = h[len-1];
    const sld = len >= 2 ? h[len-2] : null;

    if( tld.length == 2 ) {
        if( only_gov && sld != 'gov' ) return null;
        switch(  ( tld.match(exceptionRe) || [null] )[0]  ) {
         case 'uk':
            //Britain owns+uses this one
            return 'gb';
         case 'ac':
            //Ascension Island is part of the British Overseas territory
            //"Saint Helena, Ascension and Tristan da Cunha"
            return 'sh';
         case null:
            //2-letter TLD *not* in the exception list;
            //it's a valid ccTLD corresponding to its country
            return tld;
         default:
            //2-letter TLD *in* the exception list (e.g.: .eu);
            //it's not a valid ccTLD and we don't know the country
            return null;
        }
    } else if( tld == 'gov' ) {
        //AMERICAAA
        return 'us';
    } else {
        return null;
    }
}
<p>Click the following domains:</p>
<ul onclick="console.log(`${identifyCountry(event.target.textContent)} <= ${event.target.textContent}`);">
    <li>example.com</li>
    <li>example.co.uk</li>
    <li>example.eu</li>
    <li>example.ca</li>
    <li>example.ac</li>
    <li>example.gov</li>
</ul>

不过,老实说,您可以做类似的事情

function switchableMatch(s,r){
    //returns the FIRST match of r on s; otherwise, null
    const m = s.match(r);
    if(m) return m[0];
    else return null;
}

,然后再switch(switchableMatch(s,r)){…}

答案 8 :(得分:0)

您还可以使用以下默认情况:

    switch (name) {
        case 't':
            return filter.getType();
        case 'c':
            return (filter.getCategory());
        default:
            if (name.startsWith('f-')) {
                return filter.getFeatures({type: name})
            }
    }