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

use*_*622 10 perl

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#^.*/##gs/^.*\///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)


Dav*_* W. 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@;
Run Code Online (Sandbox Code Playgroud)

所有这四个表达都是一样的.他们替换字符串oldnew我的$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手.


Rob*_*t P 4

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

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

实际上,搜索并清空 value 中 / 之前的每个值,但保留脚本名称中的所有换行符。在仅适用于类 UNIX 路径的长脚本中调用时,这是获取脚本名称的一种非常懒惰的方法。

如果有机会,请考虑替换为File::BasenamePerl 中的核心模块:

use File::Basename;

# later ... 

my $script = fileparse($0);
Run Code Online (Sandbox Code Playgroud)