regex 只使用正则表达式将字符串拆分为文件名和扩展名的“元组”?

amrnrhlw  于 2022-11-18  发布在  其他
关注(0)|答案(4)|浏览(155)

我知道有更简单的方法来get file extensions with JavaScript,但部分是为了练习我的regexp技能,我想尝试使用正则表达式将文件名拆分为两个字符串,在最后一个点(.字符)之前和之后。
这是我目前掌握的情况

const myRegex = /^((?:[^.]+(?:\.)*)+?)(\w+)?$/
const [filename1, extension1] = 'foo.baz.bing.bong'.match(myRegex);
// filename1 = 'foo.baz.bing.'
// extension1 = 'bong'
const [filename, extension] = 'one.two'.match(myRegex);
// filename2 = 'one.'
// extension2 = 'two'
const [filename, extension] = 'noextension'.match(myRegex);
// filename2 = 'noextension'
// extension2 = ''

我试着用否定前瞻来表示'only match a literal .如果它后面跟着一个以结尾的单词,就像这样,把(?:\.)*改为(?:\.(?=\w+.))*
/^((?:[^.]+(?:\.(?=(\w+\.))))*)(\w+)$/gm
但是我想只使用正则表达式排除最后一个句点,并且最好在初始组中匹配'noextension',我怎么能只使用正则表达式呢?
下面是我的regexp临时文件:https://regex101.com/r/RTPRNU/1

ig9co6j1

ig9co6j11#

对于第一个捕获组,可以使用1个或多个单词字符开始匹配。然后,可以选择重复.,然后再重复1个或多个单词字符。
然后,您可以使用可选的非捕获组匹配.,并捕获组2中的1个或多个单词字符。
由于第二个非捕获组是可选的,因此第一次重复应该是贪婪的。

^(\w+(?:\.\w+)*?)(?:\.(\w+))?$

模式匹配

  • ^字符串开头
  • (捕获组1
  • \w+(?:\.\w+)*?匹配1个以上单词字符,并可选择重复.和1个以上单词字符
  • )关闭组1
  • (?:要整体匹配的非捕获组
  • \.(\w+)匹配.并在捕获组2中捕获1个以上的单词字符
  • )?关闭非捕获组并使其可选
  • $字符串结束

Regex demo

const regex = /^(\w+(?:\.\w+)*?)(?:\.(\w+))?$/;
[
  "foo.baz.bing.bong",
  "one.two",
  "noextension"
].forEach(s => {
  const m = s.match(regex);
  if (m) {
    console.log(m[1]);
    console.log(m[2]);
    console.log("----");
  }
});

另一个选项如@Wiktor Stribiżew张贴在评论中,是使用一个非贪婪的点来匹配文件名的任何字符:

^(.*?)(?:\.(\w+))?$

Regex demo

5us2dqdw

5us2dqdw2#

只是想做一个关于这个问题的最新讨论,因为我想将文件名分成“名称”和“扩展名”两部分--并且无法找到任何支持我的所有测试用例的好解决方案......我想支持以“.”开头的文件名,它应该作为“名称”返回,我还想支持没有任何扩展名的文件。
所以我用这行代码来处理我所有的用例

const [name, ext] = (filename.match(/(.+)+\.(.+)/) || ['', filename]).slice(1)

它将给予以下输出

'.htaccess' => ['.htaccess', undefined]
'foo' => ['foo', undefined]
'foo.png' => ['foo', 'png']
'foo.bar.png' => ['foo.bar', 'png']
'' => ['', undefined]

我发现这就是我想要的。

m3eecexj

m3eecexj3#

如果你真的想使用正则表达式,我建议使用两个正则表达式:

// example with 'foo.baz.bing.bong'

const firstString = /^.+(?=\.\w+)./g // match 'foo.baz.bing.' 
const secondString = /\w+$/g   // match 'bong'
wkyowqbh

wkyowqbh4#

不需要四处张望就能说得更清楚更准确的话怎么样...
1.命名组变量... /^(?<noextension>\w+)$|(?<filename>\w+(?:\.\w+)*)\.(?<extension>\w+)$/
1.没有命名组... /^(\w+)$|(\w+(?:\.\w+)*)\.(\w+)$/
两个刚刚显示的变体都可以缩短为2个捕获组,而不是上面的变体的3个捕获组,在我看来,这使得正则表达式更容易工作,代价是可读性较差...
1.命名组变量... /(?<filename>\w+(?:\.\w+)*?)(?:\.(?<extension>\w+))?$/
1.没有命名组... /(\w+(?:\.\w+)*?)(?:\.(\w+))?$/
第一个

相关问题