【问题标题】:Perl regular expression - search and replacePerl 正则表达式 - 搜索和替换
【发布时间】:2011-03-29 12:59:12
【问题描述】:

我无法理解 perl 在字符串或正则表达式中的搜索和替换。有人可以帮忙吗?

我有一个包含 HTML 的文件,如果某些项目存在于给定的集合中,我想更改它们的类(在本例中为哈希表或验证失败的已验证字段)。因此,例如,我有以下内容:

<input name="RMAProcess" type="radio" class="inputnormal" value="Good">

我想将“inputnormal”类更改为值“inputpink”。我要做的是使它匹配整个字符串 nomatter 属性出现的顺序,例如,以下内容也将匹配:

<input name="RMAProcess" type="radio" value="Good" class="inputnormal">

这是因为 Dreamweaver 在编辑过程中有时会弄乱 HTML 中的属性顺序,所以我不能依赖它们的固定位置。

所以我最终得到了一些不起作用的东西,例如:

foreach $key ( keys %FAILED ) { 
    $infile =~ s/<input type="radio" name="$key" value="$VALUES{$key}" class="([a-zA-Z]+)"/$1inputpink"/gi;
}

谁能帮我解决这个问题?

谢谢。

编辑:好的,这种工作,假设标签内的属性不移动:

foreach $key ( keys %FAILED ) {
    $infile =~ s/(<.{4,10}\ type="radio" name="$key".{1,60}class=")([a-zA-Z]+)"/$1inputpink"/gi;
}

现在必须这样做!感谢您的所有回复。

【问题讨论】:

  • 正则表达式在这类任务中真的很糟糕。我会为此推荐某种 HTML 解析器。不幸的是,我对 Perl 的了解不够,无法推荐一个。
  • @Robinson:你的意思是你不能在你的机器上安装任何 perl 模块?检查您是否有HTML::ParserHTML::TreeBuilder。也许这些模块是预先安装的,您可以使用它们来解析 HTML 而无需使用正则表达式,正如其他 cmets 中指出的那样,这不是一个好主意。
  • @Robinson:我明白了。但是,如果已经安装了这两个模块之一,请检查主机空间上的机器。您可以从命令提示符处执行此操作(假设您可以在远程计算机上打开提示符,可能是 ssh):执行perl -MHTML::Parser: 如果安装了模块,您不会收到任何错误消息,并且您使用 @ 退出 perl 解释器987654329@。其他模块 perl -MHTML::TreeBuilder 也是如此。
  • @Robinson:阅读本文,看看是否有任何选项有帮助:shadowcat.co.uk/blog/matt-s-trout/but-i-cant-use-cpan
  • 既然你说你的基本主机,我假设你可以运行 CGI。您可以使用 print "Content-type: text/plain\n\n"; eval { print "Checking for HTML::Parser\n"; require HTML::Parser; print "Found HTML::Parser\n"; }; eval { print "Checking for HTML::TreeBuilder\n"; require HTML::TreeBuilder; print "Found HTML::TreeBuilder\n"; }; 之类的脚本检查已安装的模块,添加合适的 #! 行等。

标签: regex perl


【解决方案1】:

您应该使用 HTML 解析器来解析 HTML。我用HTML::TreeBuilder

【讨论】:

    【解决方案2】:

    我建议匹配类部分,而不是匹配整个输入标签。我认为这个正则表达式应该可以工作......

    my $htmlLine = "<input name=\"RMAProcess\" type=\"radio\" class=\"inputnormal\" value=\"Good\">";
    $htmlline =~s/class="inputnormal"/class="inputpink"/i;
    

    【讨论】:

    • 那行得通,是的。我会将此标记为答案。谢谢。
    【解决方案3】:

    如果你有选择,

    $ cat file
    <input name="RMAProcess" type="radio" class="inputnormal" value="Good">
    <input name="RMAProcess" type="radio" value="Good" class="inputnormal">
    
    $ ruby -ne 'print $_.gsub(/(.*class=")(.[^"]*)(".*)/, "\\1inputpink\\3"  ) ' file
    <input name="RMAProcess" type="radio" class="inputpink" value="Good">
    <input name="RMAProcess" type="radio" value="Good" class="inputpink">
    

    它只是用反向引用替换,所以正则表达式也可以在 Perl 上下文中使用......

    如果您需要确保有name="", type="", value="",则使用if 例如

    ruby -ne 'print $_.gsub(/(.*class=")(.[^"]*)(".*)/, "\\1inputpink\\3"  ) if /name=/&&/type=/&&/value=/' file
    

    【讨论】:

    • 如果我错了,请纠正我,但你只是在这里匹配 class="x"。我想匹配 name="x" type="y" value="z" 然后替换尖括号内的 class="p" 值。对不起,我没有说清楚。
    【解决方案4】:

    分两步可能更容易做到这一点:

    1. 通过在属性上创建散列或运行多个 reg.exp,将行拆分为属性并检查“name=X”和“type=y”是否。

    2. 如果你想换行,你可以用一个简单的 reg.exp 替换 class

    【讨论】:

      【解决方案5】:

      如果您无法安装任何模块,您可以尝试类似:

      #!/usr/bin/perl
      use Modern::Perl;
      
      
      my %FAILED = (RMAProcess => 'Good');
      
      while (my $line = <DATA>) {
          chomp($line);
          foreach my $key ( keys %FAILED ) { 
              if ($line =~ /type="radio"/ && $line =~ /name="$key"/ && $line =~/value="$FAILED{$key}"/) {
                  $line =~ s/class="([a-zA-Z]+)"/class="inputpink"/;
              }
          }
          say $line;
      }
      
      __DATA__
      <input name="RMAProcess" type="radio" class="inputnormal" value="Good">
      <input name="RMAProcess" type="radio" value="Good" class="inputnormal">
      

      输出:

      <input name="RMAProcess" type="radio" class="inputpink" value="Good">
      <input name="RMAProcess" type="radio" value="Good" class="inputpink">
      

      【讨论】:

        猜你喜欢
        • 2012-08-30
        • 2013-06-14
        • 2018-05-25
        • 2010-11-25
        • 2010-10-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多