scriptOJ开局第一题——接收文件名作为参数,返回后缀名

前言:scriptOJ 是首个 Web 前端开发评测系统,上面有很多前端题目,和一部分算法,前端人的OJ系统,没用过的小伙伴可以尝试下。

  很早就听说这个网站了,不过开局第一题一直写不出来,今天又看了一下总算是搞定了,在我的解法中用到了比较多的有关正则方面的知识,在这里总结一下。


下面就是进入首页会看到的第一题(好像定期会更换):

scriptOJ开局第一题——接收文件名作为参数,返回后缀名


下面是我的解法:

const extname = (filename) => {
  let re = /\.[a-zA-Z]+/ig;
  
  if (re.test(filename)) { // 第一次匹配
    if (RegExp.leftContext == '') { // 第一次匹配左边没有字符(只有后缀名)
      return '';
    }

    let a = filename.match(re); // match会将匹配到的所有字符储存在一个数组中并返回

    return a[a.length - 1]; // 返回最后一次匹配到的字符串
  } else {
    return ''; // 没有匹配到任何后缀名,直接返回空字符串
  } 
}

用于测试的数据大概有这么几种:

var str1 = 'test.ms.hello.jpg';  // 有很多 . 分割的字符串,但只有最后一个才是后缀名
var str2 = '.png';               // 只有后缀名,要求返回一个空字符串
var str3 = 'hello';              // 没有后缀名,要求返回一个空字符串

总结一下解题中用到的正则相关的知识:

  • RegExp构造函数的属性
    • input:用于匹配的字符串
    • lastMatch:最近一次匹配到的字符串
    • lastParen:最近一次匹配到的捕获组
    • leftContext:input中lastMatch之前的字符串
    • rightContext:input中lastMatch之后的字符串
    • multiline:匹配是否用于多行模式

这些属性Opera均不支持,最后一个属性IE不支持

举例:

var str= "this has been a short summer";
var re= /(.)hort/g;

if (re.test(str)) {
  console.log(RegExp.input);         // this has been a short summer
  console.log(RegExp.lastMatch);     // short 
  console.log(RegExp.lastParen);     // s
  console.log(RegExp.leftContext);   // this has been a 
  console.log(RegExp.rightContext);  // summer
  console.log(RegExp.multiline);     //false
}

解题中用到了:leftContext属性,通过判断第一次匹配之前是否有字符串,来判断是不是只有后缀名这种情况。

  • RegExp实例的方法
    • test()
    • exec()

用法:re.test(str);re.exec(str)

re是正则表达式的实例,str是用于匹配的字符串

test() 方法返回boolean类型的值,匹配到返回true,未匹配到返回false
exec() 方法没有匹配到时返回null,匹配到时返回一个数组

该数组额外具有两个属性:indexinputindex指匹配项在字符串中的位置,input指用于匹配的字符串。

exec方法返回的数组中第一项就是匹配到的字符串 :

var str = 'test.ms.hello.jpg';
var re = /\.[a-zA-Z]+/ig;
var a = re.exec(str);

console.log(a[0]);  // .ms

不使用全局模式时,多次调用 exec() 得到的结果都是只返回第一次匹配的结果

var str = 'test.ms.hello.jpg';
var re = /\.[a-zA-Z]+/i;
var a = re.exec(str);
console.log(a[0]);  // .ms

a = re.exec(str);
console.log(a[0]);  // .ms

a = re.exec(str);
console.log(a[0]);  // .ms

但是,当使用全局模式时,多次调用 exec() 时,每次调用exec() 都会返回字符串中下一个匹配项

var str = 'test.ms.hello.jpg';
var re = /\.[a-zA-Z]+/ig;
var a = re.exec(str);
console.log(a[0]);  // .ms

a = re.exec(str);
console.log(a[0]);  // .hello

a = re.exec(str);
console.log(a[0]);  // .jpg

至于为什么,就要涉及到RegExp实例lastIndex属性:

待续~