【问题标题】:How For loop will work in perlFor 循环如何在 perl 中工作
【发布时间】:2013-01-08 06:33:06
【问题描述】:
#!/usr/bin/perl
@lines = `perldoc -u -f atan2`;
foreach (@lines) {
  s/\w<([^>]+)>/\U$1/g;
  print;
}

表达式s/\w&lt;([^&gt;]+)&gt;/\U$1/g;如何工作?

【问题讨论】:

  • regex explainer 是一个非常有用的工具。 :)
  • @TedHopp 那个正则表达式解释器似乎对这个正则表达式抛出了一些问题。我认为那是因为它无法处理替换。
  • foreach 循环中的内容不应该在某处有$_ 吗?
  • @slayedbylucifer $_ 默认用于替换和打印。还有其他事情。
  • @slayedbylucifer:这是 Perl 的核心概念,$_ 的全部意义都存在。

标签: perl


【解决方案1】:

替换是这样做的:

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 修饰符以便能够可视化正则表达式。字符类[^&gt;] 被否定,如[ 后面的^ 字符表示,表示“除&gt; 之外的任何字符”。

例如,在 perldoc 命令的输出中

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

改为

ATAN2 ARCTANGENT TAN TANGENT

【讨论】:

    【解决方案2】:

    这是另一种了解它在做什么的选项。使用来自 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”之间进行的匹配应该转换为大写。

    【讨论】:

      【解决方案3】:

      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 用法)。

      【讨论】:

      • 我认为你应该忽略关于 perl 可读性的煽动性声明。记住没有目标变量的for 使用$_ 并不难。
      • 同意。这些快捷方式和编写结构的替代方法允许优秀的编码人员选择何时冗长以及何时尽可能简短,以使代码更具可读性和可维护性。通常写像send_hello($_) foreach @people; 这样简单的东西可读性很强,而包含多条指令的循环可能最好写成foreach my $person (@people) { ... }
      • @plusplus:不同意。正是因为省略变量的能力使得阅读 perl 几乎是不可能的(在开始之前你必须知道意图)。用 perl 编写可维护的代码需要一个训练有素的优秀程序员(不使用快捷方式)(而且由于大多数 perl 猴子都没有训练有素,这种语言已经获得了一次编写(不再阅读)的美誉)语言。
      • @plusplus:另一方面,这也使 perl 成为一个非常好的资源,因为它使初学者无法进入,并且 cpan 中的项目维护仅由作者完成。因此,与 php 不同的是,代码通常很好(即使您无法阅读,除非您是作者)。
      • @LokiAstari 正是因为你的陈述的这种争论性质,我建议你把它排除在外。我在阅读 perl 时没有问题。 stackoverflow.com/q/9591658/725418 如果你看不懂 perl,那可能是因为你不够熟练,而不是因为 cpan 的作者写了草率的代码。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-07-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多