Regex Golf:在最后一个“/”之后切掉一切

时间:2013-03-01 13:27:20

标签: regex perl

这个问题纯粹是化妆的:

我想删除给定字符串的最后一个“/”之后的所有文本。所以如果输入是

mkdir -p $DEST/Users/Peter/Dropbox/Public/Vacation/P1000891.jpg

输出应为

mkdir -p $DEST/Users/Peter/Dropbox/Public/Vacation/

(确切地说,输出中是否包含最后一个“/”并不重要。)

我找到了各种方法,例如:

my @templist = split "/", 'mkdir -p $DEST/Users/Peter/Dropbox/Public/Vacation/P1000891.jpg';
print join "/", splice(@templist, 0, -1);

或者:

my ($a) = 'mkdir -p $DEST/Users/Peter/Dropbox/Public/Vacation/P1000891.jpg' =~ /(.*\/)+(?:[^\/]+)/;
print $a;

但是我认为这应该只使用正则表达式来实现,也许只能使用搜索&更换?也许有先见之明?

5 个答案:

答案 0 :(得分:7)

只需删除字符串末尾的所有非斜杠字符:

s|[^/]+$||;

顺便说一下,前瞻是一种检查模式中某个位置发生某种事情的方法,而不是实际向前移动匹配位置。简单的匹配任务很少需要它,但是那些不太了解它的人似乎过度使用它。

答案 1 :(得分:2)

use File::Basename qw( dirname );
dirname($path)

答案 2 :(得分:1)

s/(.*\/).*$/$1/g

测试如下:

> echo "a/b/c/d/e/f/remove this"|perl -pe 's/(.*\/).*$/$1/g'
a/b/c/d/e/f/

答案 3 :(得分:1)

您提到正则表达式 perl 作为标记。问题(正如你所发现的)是正则表达式是贪婪的。有两种方法可以解决这个问题:

  • 旧方法:在较早版本的grepsed中,您拥有一组有限的正则表达式。你所做的就是利用你不想要删除任何斜线的事实。

因此:

$directory =~ s(/[^/]+$)();

(我使用括号作为正则表达式分隔符,所以我没有山丘和山谷影响如下:s/\/[^\/]//)。这是说从最后匹配所有现在正斜杠字符前面的正斜杠,然后什么都不替换。

但是,它看起来只是想要从目录中删除文件名。 Perl有一种内置的处理方式。它被称为dirname函数:

use File::Basename;

[...];

print "mkdir -p " . dirname $directory . "\n";

这使得你非常清楚地知道自己在做什么。此外,它将适用于替代操作系统,这些操作系统不使用标准正斜杠进行目录分离(咳嗽 Windows!咳嗽

答案 4 :(得分:0)

以前的解决方案比我的好,但我想与您分享:

perl -e 'my $str = "mkdir -p \$DEST/Users/Peter/Dropbox/Public/Vacation/P1000891.jpg"; my ($res)=$str=~m|(.+/)|; print $res;'

打印:

  

mkdir -p $ DEST / Users / Peter / Dropbox / Public / Vacation /

所以,m|(.+/)|贪婪地吞噬了一切,直到最后一次" /"。然后我们说应该有一个" /"在我们关注的部分。