通过环顾查找形态的最后一次出现

Finding last occurrence of a pattern with lookaround

提问人:LucasCS 提问时间:10/29/2023 更新时间:10/30/2023 访问量:103

问:

我有路径,只想在最终和使用正则表达式之间提取。文件扩展名也并不总是 .../dir1/dir2/dir3/filename.txtfilename\..txt

目前我正在做,但从第一个选择,包括目录名称。我希望这只是基于比赛而不是使用组。哦,如果这很重要,请使用 ECMA 正则表达式。(?<=\/).+(?=\.)\

JavaScript 正则表达式 Lookarounds

评论

0赞 dandavis 10/29/2023
有时将其分解成碎片更简单:比 RX FOO 更容易阅读/维护。strPath.split(/\//).pop().split(/\./)[0]
0赞 Cary Swoveland 10/29/2023
我不了解 Javascript,但有些语言提供了从完全限定路径中提取文件名和扩展名的方法或函数。例如,在 Ruby 中,如果 、.f = "../dir1/dir2/dir3/filename.txt"File.basename(f).delete(File.extname(f)) #=> "filename"
0赞 Cary Swoveland 10/30/2023
如果完全限定的文件名没有扩展名,您是否希望返回,例如 What would you want return if it are?隐藏文件呢,例如?"dog""../dir/dog""../dir/cat.tar.gz""../dir/.pig.pen"

答:

2赞 mandy8055 10/29/2023 #1

您可以使用以下正则表达式来实现您的目的:

([\w-]+)\..*$

上述正则表达式的解释:

  • ([\w-]+) - 与一个或多个 (+) 单词字符 (\w) 或连字符 (-) 匹配的捕获组。通常文件名包含\w字符,所以我使用了它,但是如果它包含其他特殊字符,请根据您的需要随意修改它。
  • \。- 匹配文字点字符。
  • .* - 匹配任何字符 (.) 零次或多次 (*)。
  • $- 匹配行尾。因此,基本上完整的正则表达式匹配任何包含单词(由一个或多个单词字符或连字符组成)的字符串,后跟一个点和任何字符,直到行尾。点前的单词被捕获以供以后使用,此捕获组为您提供所需的 .filename

enter image description here

const regex = /.*?([\w-]+)\..*$/gm;

const str = `../dir1/dir2/dir3/filename1.tar.gz
../dir1/dir2/dir3/filename2.tar`;
const subst = `$1`;

// The substituted value will be contained in the result variable
const result = str.replace(regex, subst);

console.log(result);

REGEX 演示

替代方法:(使用Javascript函数)

let paths = `../dir1/dir2/dir3/filename1.tar.gz
../dir1/dir2/dir3/filename2.tar`;

paths.split('\n').forEach(path => console.log(path.  
split('/').pop().split('.').shift()));

/* 
* split('/').pop() - splits the path into an array using the forward slash (/) as the separator
and removes and returns the last element of the array.  

* split('.').shift() - splits the filename into an array using the dot (.) as the separator, 
and removes and returns the first element of the array.
* NOTE: paths.split('\n') might not be your exact requirement. I used it to showcase.
*/

评论

0赞 Cary Swoveland 10/29/2023
不要忘记,基名不需要扩展名。
0赞 mandy8055 10/29/2023
@CarySwoveland谢谢。如果是这样的话,这将有所帮助。此外,我相信 OP 在最后的 \ 和 . 之间提到了提取文件名,这就是为什么我没有添加这个,但是是的,如果需要,我可以这样做。
1赞 LucasCS 10/30/2023
谢谢!这两个答案都很棒:)
1赞 PCDSandwichMan 10/30/2023
我喜欢这个答案。非常详细,几个例子,以及很好的解释。很棒的工作。
2赞 Cary Swoveland 10/29/2023 #2

如果匹配正则表达式

\/(?:(\.?[^./][^/]*)\.[^./]+|(\.?[^./]+))$

也:

  • 有一个文件扩展名,在这种情况下,捕获组 1 将保留不带扩展名的 basename,而捕获组 2 将为空;或
  • basename 没有扩展名,在这种情况下,捕获组 2 将保留 basename,而捕获组 1 将为空。

演示

我们可以将这个表达式分解如下。

\/         # match a forward slash 
(?:        # begin non-capture group
  (        # begin capture group 1
     \.?   # optionally match a period (for hidden files)
    [^/]+  # match one or more chars other than (`^`) a forward slash
  )        # end capture group 1
  \.       # match a period
  [^./]+   # match one or more chars other than a period or forward slash
|          # or
  (        # begin capture group 2
     \.?   # optionally match a period (for hidden files)
    [^./]+ # match one or more chars other than a period or forward slash
  )        # end capture group 2
)          # end non-capture group
$          # match the end of the string

您可能还希望将鼠标悬停在链接处表达式的不同部分(光标,而不是您的人)上,以获取对其功能的解释。


如果知道基名具有扩展名,则正则表达式将以明显的方式简化,使用单个捕获组:

(\.?[^/]+)\.[^./]+$

演示

评论

0赞 LucasCS 10/30/2023
非常感谢!这个答案和其他答案对我来说都很好:)!