perl中以下语句的含义是什么?
($script = $0) =~ s#^.*/##g;
Run Code Online (Sandbox Code Playgroud)
我试图理解operator =〜以及右侧的声明#^.*/## g.
谢谢
Sch*_*ern 28
=~将右边的东西(模式匹配或搜索和替换)应用于左侧的东西.那里有很多关于=~那里的文档,所以我只想指出一个非常好的文档.
那里有几个成语,这些成语并不明显,也没有很好的记录可能会让你沮丧.我们来盖他们.
首先是这......
($copy = $original) =~ s/foo/bar/;
Run Code Online (Sandbox Code Playgroud)
这是一种复制变量并在一个步骤中执行搜索和替换的方法.它相当于:
$copy = $original;
$copy =~ s/foo/bar/;
Run Code Online (Sandbox Code Playgroud)
该=~对什么是左侧操作后,左手码已运行. ($copy = $original)计算结果为$copy这样=~的副本行为.
s#^.*/##g与s/^.*\///g使用替代分隔符相同,以避免倾斜牙签综合征.你可以使用任何东西作为正则表达式分隔符. #很常见,虽然我认为它丑陋且难以阅读.我更喜欢{}因为他们平衡. s{^.*/}{}g是等效的代码.
展开成语,你有这个:
$script = $0;
$script =~ s{^.*/}{}g;
Run Code Online (Sandbox Code Playgroud)
$0是脚本的名称.所以这是复制脚本名称的代码,并将所有内容都删除到最后一个斜线(.*贪婪且尽可能匹配).它只是获取脚本的文件名.
在/g表示要执行的字符串匹配多次越好.因为这只能匹配一次(将^它锚定到字符串的开头),所以没有任何意义.
有一个更好,更安全的方法来做到这一点.
use File::Basename;
$script = basename($0);
Run Code Online (Sandbox Code Playgroud)
它非常非常简单:
类似于 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@;
Run Code Online (Sandbox Code Playgroud)
所有这四个表达都是一样的.他们替换字符串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!
Run Code Online (Sandbox Code Playgroud)
最后一个仍然有效,因为像运算符的引用计算开括号和结束括号.当然,对于正则表达式,括号和方括号是正则表达式语法的一部分,因此您不会在替换中看到它们.
大多数情况下,强烈建议您坚持使用s/.../.../表单以便于阅读.这是人们习惯使用的东西,很容易消化.但是,如果你有这个怎么办?
$bin_dir =~ s/\/home\/([^\/]+)\/bin/\/Users\/$1\bin/;
Run Code Online (Sandbox Code Playgroud)
那些反斜杠可能使它难以阅读,因此传统的做法是更换反斜杠分离器以避免山丘和山谷的影响.
$bin_dir =~ s#/home/([^/]+)/bin#/Users/$1/bin#;
Run Code Online (Sandbox Code Playgroud)
这有点难以阅读,但至少我不必引用每个正斜杠和反斜杠,所以更容易看到我替换的是什么.正则表达式很难,因为很难找到好的引号字符.各种特殊符号,如^,*,|,和+是神奇的正则表达式字符,并且很可能是在正则表达式中,#是一个普遍使用.它在字符串中并不常见,并且在正则表达式中没有任何特殊含义,因此不会使用它.
回到原来的问题:
($script = $0) =~ s#^.*/##g;
Run Code Online (Sandbox Code Playgroud)
相当于:
($script = $0) =~ s/^.*\///g;
Run Code Online (Sandbox Code Playgroud)
但由于原始程序员不想反驳斜杠,他们改变了分隔符.
至于:
($ script = $ 0)=〜s#^.*/## g;`
这跟说:
$script = $0;
$script =~ s#^.*/##g;
Run Code Online (Sandbox Code Playgroud)
您将分配$script变量并在一个步骤中执行替换.它在Perl中很常见,但起初有点难以理解.
顺便说一下,如果我理解了基本表达式(将所有字符删除到最后一个正斜杠.这样会更清晰:
use File::Basename;
...
$script = basename($0);
Run Code Online (Sandbox Code Playgroud)
更容易阅读和理解 - 即使是旧的Perl手.
在 perl 中,您可以使用多种字符作为引用字符(字符串、正则表达式、列表)。让我们分解一下:
$script将变量的内容分配给$0(包含调用脚本名称的字符串。)=~字符是绑定运算符。 它调用正则表达式匹配或正则表达式搜索和替换。在本例中,它与新变量 匹配$script。s字符表示搜索和替换正则表达式。#字符用作正则表达式的分隔符。正则表达式模式引号字符通常是/字符,但您可以使用其他字符,包括#在本例中。^.*/. 它的意思是,“在字符串的开头,搜索零个或多个字符,直到出现斜杠。这将继续捕获除换行符(.默认情况下不匹配)之外的每一行。”#“替换”值的开始。通常,您在这里有一个使用第一行的任何捕获部分的模式。#。替换模式就此结束。由于替换模式的开始和结束之间没有任何内容,因此第一个模式中找到的所有内容都将被替换为任何内容。g,或全局匹配。搜索和替换将持续发生与值匹配的次数。实际上,搜索并清空 value 中 / 之前的每个值,但保留脚本名称中的所有换行符。在仅适用于类 UNIX 路径的长脚本中调用时,这是获取脚本名称的一种非常懒惰的方法。
如果有机会,请考虑替换为File::BasenamePerl 中的核心模块:
use File::Basename;
# later ...
my $script = fileparse($0);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3404 次 |
| 最近记录: |