perl中以下语句的含义是什么?
($script = $0) =~ s#^.*/##g;
我试图理解operator =〜以及右侧的声明#^。* / ## g。
由于
答案 0 :(得分:28)
=~
将右侧的东西(模式匹配或搜索和替换)应用于左侧的东西。那里有很多关于=~
的文档,所以我只是去point you at a pretty good one。
那里有几个成语,这些成语并不明显,也没有很好的记录,可能会使你绊倒。我们来掩盖他们。
首先是这个......
($copy = $original) =~ s/foo/bar/;
这是一种复制变量并在一个步骤中执行搜索和替换的方法。它相当于:
$copy = $original;
$copy =~ s/foo/bar/;
运行左侧代码后,=~
对左侧上的任何内容进行操作。 ($copy = $original)
评估为$copy
,因此=~
会对副本进行操作。
s#^.*/##g
与s/^.*\///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。对于q
和qq
而言,这可以很好地用于代替单引号和双引号:
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);