Perl正则表达式匹配中数字符号(#)的含义是什么?

时间:2013-01-15 00:39:50

标签: perl

perl中以下语句的含义是什么?

($script = $0) =~ s#^.*/##g;

我试图理解operator =〜以及右侧的声明#^。* / ## g。

由于

3 个答案:

答案 0 :(得分:28)

=~将右侧的东西(模式匹配或搜索和替换)应用于左侧的东西。那里有很多关于=~的文档,所以我只是去point you at a pretty good one

那里有几个成语,这些成语并不明显,也没有很好的记录,可能会使你绊倒。我们来掩盖他们。

首先是这个......

($copy = $original) =~ s/foo/bar/;

这是一种复制变量并在一个步骤中执行搜索和替换的方法。它相当于:

$copy = $original;
$copy =~ s/foo/bar/;

运行左侧代码后,=~对左侧上的任何内容进行操作。 ($copy = $original)评估为$copy,因此=~会对副本进行操作。

s#^.*/##gs/^.*\///g相同,但使用alternative delimiters来避免Leaning Toothpick Syndrome。你可以使用任何东西作为正则表达式分隔符。 #很常见,但我觉得它丑陋且难以阅读。我更喜欢{},因为他们保持平衡。 s{^.*/}{}g是等效的代码。

展开成语,你有这个:

$script = $0;
$script =~ s{^.*/}{}g;

$0是脚本的名称。所以这是复制脚本名称的代码,并将所有内容都删除到 last 斜杠(.*贪婪且尽可能匹配)。它只是获取脚本的文件名。

/g表示尽可能多地对字符串执行匹配。因为这只能匹配一次(^将它锚定到字符串的开头),所以没有用处。

这是一种更好,更安全的方法。

use File::Basename;
$script = basename($0);

答案 1 :(得分:5)

非常非常简单:

Perl 类似于引用的表达式可以将许多不同的字符作为部分分隔符。命令后面的分隔符(在本例中为s)是其余操作的分隔符。例如:

 # Out with the "Old" and "In" with the new

 $string =~ s/old/new/;
 $string =~ s#old#new#;
 $string =~ s(old)(new);
 $string =~ s@old@new@;

所有这四个表达都是一回事。他们将old中的字符串new替换为$string。无论s之后是什么,都是分隔符。请注意,括号,花括号和方括号使用parings。对于qqq而言,这可以很好地用于代替单引号和双引号:

print "The value of \$foo is \"foo\"\n";   # A bit hard to read
print qq/The value of \$foo is "$foo"\n/;  # Maybe slashes weren't a great choice...
print qq(The value of \$foo is "$foo"\n);  # Very nice and clean!
print qq(The value of \$foo is (believe it or not) "$foo"\n); #Still works!

最后一个仍然有效,因为像运算符这样的引用会计算开括号和结束括号。当然,对于正则表达式,括号和方括号是正则表达式语法的一部分,因此您不会在替换中看到它们。

大多数情况下,强烈建议您坚持使用s/.../.../表单以提高可读性。这是人们习惯使用的东西,很容易消化。但是,如果你有这个怎么办?

$bin_dir =~ s/\/home\/([^\/]+)\/bin/\/Users\/$1\bin/;

那些反斜杠会让它难以阅读,所以传统上一直是替换反斜杠分隔符以避免丘陵和山谷效应

$bin_dir =~ s#/home/([^/]+)/bin#/Users/$1/bin#;

这有点难以阅读,但至少我不必引用每个正斜杠和反斜杠,所以更容易看到我替换的是什么。正则表达式很难,因为很难找到好的引号字符。 ^*|+等各种特殊符号都是神奇的正则表达式字符,可能是正则表达式{{1}是一个常用的。它在字符串中并不常见,并且在正则表达式中没有任何特殊含义,因此不会被使用。


回到原来的问题:

#

相当于:

($script = $0) =~ s#^.*/##g;

但是因为原来的程序员不想反驳斜杠,所以他们改变了分隔符。

至于:

($ script = $ 0)=〜s#^。* / ## g;`

与说法相同:

($script = $0) =~ s/^.*\///g;

您正在分配$script = $0; $script =~ s#^.*/##g; 变量并在一个步骤中执行替换。它在Perl中很常见,但最初有点难以理解。

顺便说一下,如果我理解了这个基本表达式(将所有字符删除到最后一个正斜杠。这样会更清晰:

$script

更容易阅读和理解 - 即使对于旧的Perl手也是如此。

答案 2 :(得分:4)

在perl中,您可以使用多种字符作为引号(字符串,正则表达式,列表)。让我们分解一下:

  • $script变量分配$0的内容(包含调用脚本名称的字符串。)
  • =~字符是binding operator.它调用正则表达式匹配或正则表达式搜索和替换。在这种情况下,它与新变量$script匹配。
  • s字符表示搜索并替换正则表达式。
  • #字符用作正则表达式的分隔符。正则表达式模式引号字符通常是/字符,但您可以使用其他字符,在这种情况下包括#
  • 正则表达式,^.*/。这意味着,“在字符串的开头,搜索零个或多个字符,直到斜线。这将继续捕获除换行符之外的每一行(默认情况下.不匹配。)
  • #表示'替换'值的开始。通常你在这里有一个模式,它使用第一行的任何捕获部分。
  • 再次#。这结束了替换模式。由于在替换模式的开始和结束之间没有任何内容,因此在第一个中找到的所有内容都不会被替换。
  • g,或全局匹配。搜索和替换将继续发生与值匹配的次数。

实际上,搜索并清空值中/之前的每个值,但保留脚本名称中的所有换行符。在长脚本中调用脚本名称时,这是一种非常懒惰的方式,只能使用类似unix的路径。

如果您有机会,请考虑使用Perl中的核心模块File::Basename替换:

use File::Basename;

# later ... 

my $script = fileparse($0);