3
#!/usr/bin/perl
@lines = `perldoc -u -f atan2`;
foreach (@lines) {
  s/\w<([^>]+)>/\U$1/g;
  print;
}

表达式将如何s/\w<([^>]+)>/\U$1/g;工作?

4

3 回答 3

4

替换是这样做的:

s/             
    \w<         # look for a single alphanumeric character followed by <
    ([^>]+)     # capture one or more characters that are not <
    >           # followed by a >
/               ### replace with
   \U           # change following text to uppercase
   $1           # the captured string from above
/gx             # /g means do this as many times as possible per line

我添加了/x修饰符以便能够可视化正则表达式。字符类[^>]被否定,如^之后的字符表示[,表示“除”之外的任何字符>

例如,在 perldoc 命令的输出中

X<atan2> X<arctangent> X<tan> X<tangent>

改为

ATAN2 ARCTANGENT TAN TANGENT
于 2013-01-08T06:41:22.237 回答
4

这是弄清楚它在做什么的另一种选择。使用来自 CPAN的模块YAPE::Regex::Explain 。

以这种方式使用它(这只是搜索和替换的匹配部分):

use strict;
use YAPE::Regex::Explain;

print YAPE::Regex::Explain->new(qr/\w<([^>]+)>/)->explain();

将给出这个输出:

The regular expression:

(?-imsx:\w<([^>]+)>)

matches as follows:

NODE                     EXPLANATION
----------------------------------------------------------------------
(?-imsx:                 group, but do not capture (case-sensitive)
                         (with ^ and $ matching normally) (with . not
                         matching \n) (matching whitespace and #
                         normally):
----------------------------------------------------------------------
  \w                       word characters (a-z, A-Z, 0-9, _)
----------------------------------------------------------------------
  <                        '<'
----------------------------------------------------------------------
  (                        group and capture to \1:
----------------------------------------------------------------------
    [^>]+                    any character except: '>' (1 or more
                             times (matching the most amount
                             possible))
----------------------------------------------------------------------
  )                        end of \1
----------------------------------------------------------------------
  >                        '>'
----------------------------------------------------------------------
)                        end of grouping
----------------------------------------------------------------------

表达式的替换部分说明早先在“group and capture to \1”和“end of \1”之间进行的匹配应转换为大写。

于 2013-01-08T11:00:44.317 回答
0

perl 循环如下所示:

foreach $item (@array)
{
   # Code in here. ($item takes a new value from array each iteration)
}

但是 perl 允许您几乎在任何地方都省略变量。
当您这样做时,将$_使用特殊变量。

所以在你的情况下:

foreach (@lines) 
{
}

与以下内容完全相同:

foreach $_ (@lines) 
{
}

现在在正文中添加以下代码:

s/\w<([^>]+)>/\U$1/g;

有同样的事情发生。您实际上正在处理一个变量。而当你不指定变量时,perl 默认为$_.

因此它相当于:

$_ =~ s/\w<([^>]+)>/\U$1/g;

将两者结合起来:

foreach (@lines) {
  s/\w<([^>]+)>/\U$1/g;
  print;
}

也等价:

foreach $item (@lines)
{
    $item =~ s/\w<([^>]+)>/\U$1/g;
    print $item;
}

$item只是为了可读性。在内部它意味着$_.

许多 perl 代码使用这种类型的快捷方式。就我个人而言,我认为它使阅读变得更加困难(即使对于有经验的 perl 程序员也是如此(这是 perl 以不可读而闻名的原因之一))。因此,我总是尝试明确变量的使用(但这(我的用法)不是典型的 perl 用法)。

于 2013-01-08T06:55:57.073 回答