2

这个问题纯粹是装饰性的:

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

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;

但我认为这应该只使用正则表达式就可以实现,也许使用搜索和替换?也许与前瞻?

4

5 回答 5

7

只需去掉字符串末尾的所有非斜线字符:

s|[^/]+$||;

顺便说一句,前瞻是一种检查模式中稍后发生的事情的方法,而无需实际向前移动匹配位置。简单的匹配任务很少需要它,但它似乎被不太清楚它是什么的人过度使用了。

于 2013-03-01T13:29:32.280 回答
2
use File::Basename qw( dirname );
dirname($path)
于 2013-03-01T13:48:32.583 回答
1
s/(.*\/).*$/$1/g

测试如下:

> echo "a/b/c/d/e/f/remove this"|perl -pe 's/(.*\/).*$/$1/g'
a/b/c/d/e/f/
于 2013-03-01T13:36:36.783 回答
1

您提到了正则表达式perl作为标签。问题(正如您所发现的)是正则表达式是贪婪的。有两种方法可以处理此问题:

  • 旧方法:在旧版本的grepandsed中,您只有一组有限的正则表达式。您所做的是利用您不希望在要删除的内容中出现任何斜线的事实。

因此:

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

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

但是,看起来您只是想从目录中删除文件名。Perl 有一个内置的方法来处理这个问题。它被称为dirname函数:

use File::Basename;

[...];

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

这使您非常非常清楚您在做什么。此外,它还可以在不使用标准正斜杠进行目录分隔的替代操作系统上运行(咳咳咳咳

于 2013-03-01T13:55:23.547 回答
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|(.+/)|贪婪地吞噬一切,直到最后一个“/”。然后我们说我们关心的部分应该有一个“/”。

于 2013-03-01T15:46:12.413 回答