【问题标题】:Perl string replacements of file paths in text file文本文件中文件路径的 Perl 字符串替换
【发布时间】:2013-07-17 05:11:27
【问题描述】:

我正在尝试匹配文本文件中的文件路径并将它们替换为它们的共享文件路径。例如。我想用"\\Project_Security$" 替换字符串"X:\Group_14\Project_Security"

我在理解语法时遇到了问题,因为我使用了反斜杠 (\) 来转义另一个反斜杠 (\\) 但这似乎不适用于匹配文本文件。

open INPUT, '< C:\searchfile.txt';
open OUTPUT, '> C:\logsearchfiletest.txt';
@lines = <INPUT>;
%replacements = (
    "X:\\Group_14\\Project_Security" => "\\\\Project_Security\$",
    ...
    (More Paths as above)
    ...
);
$pattern = join '|', keys %replacements;
for (@lines) {
    s/($pattern)/@{[$replacements{$1}]}/g;
    print OUTPUT;
}

不完全确定发生了什么"\\\\Project_Security\$" 正确显示为\\Project_Security$"

所以我认为问题在于"X:\\Group_14\\Project_Security" 未正确评估为
"X:\Group_14\Project_Security" 因此在文本文件中不匹配?

对此的任何建议将不胜感激,干杯。

【问题讨论】:

    标签: string perl replace


    【解决方案1】:

    如果所有文件路径和替换的格式与您的示例类似,您应该能够执行以下操作,而不是使用哈希来查找替换:

    for my $line (@lines) {
        $line =~ s/.+\\(.+)$/\\\\$1\$/;
        print OUTPUT $line;
    }
    

    【讨论】:

    • 使用散列的原因是他希望每行一次遍历 600 对搜索字符串和替换,而不是必须为 150,000 行中的每一行运行 600 次正则表达式引擎。请参阅我刚刚发布的原始问题的链接。
    • 我是按照他的实际问题进行的,而不是发布的代码。他暗示他想替换这样的路径:“X:\Group_14\Project_Security”,共享如下:“\\Project_Security$”。在这种情况下,我发布的正则表达式将更加高效和可扩展。
    【解决方案2】:

    一些注意事项:

    • 始终使用 3 参数 open
    • 始终检查打开、打印或关闭时的错误
    • 有时使用循环比使用巧妙的编码更容易

    试试:

    #!/usr/bin/env perl
    
    use strict;
    use warnings;
    
    # --------------------------------------
    
    use charnames qw( :full :short   );
    use English   qw( -no_match_vars );  # Avoids regex performance penalty
    
    use Data::Dumper;
    
    # Make Data::Dumper pretty
    $Data::Dumper::Sortkeys = 1;
    $Data::Dumper::Indent   = 1;
    
    # Set maximum depth for Data::Dumper, zero means unlimited
    local $Data::Dumper::Maxdepth = 0;
    
    # conditional compile DEBUGging statements
    # See http://lookatperl.blogspot.ca/2013/07/a-look-at-conditional-compiling-of.html
    use constant DEBUG => $ENV{DEBUG};
    
    # --------------------------------------
    
    # place file names in variables to they are easily changed
    my $search_file     = 'C:\\searchfile.txt';
    my $log_search_file = 'C:\\logsearchfiletest.txt';
    
    my %replacements = (
      "X:\\Group_14\\Project_Security" => "\\\\Project_Security\$",
      # etc
    );
    
    # use the 3-argument open as a security precaution
    open my $search_fh,     '<', $search_file     or die "could not open $search_file: $OS_ERROR\n";
    open my $log_search_fh, '>', $log_search_file or die "could not open $log_search_file: $OS_ERROR\n";
    
    while( my $line = <$search_fh> ){
    
      # scan for replacements
      while( my ( $pattern, $replacement ) = each %replacements ){
        $line =~ s/\Q$pattern\E/$replacement/g;
      }
    
      print {$log_search_fh} $line or die "could not print to $log_search_file: $OS_ERROR\n";
    }
    
    # always close the file handles and always check for errors
    close $search_fh     or die "could not close $search_file: $OS_ERROR\n";
    close $log_search_fh or die "could not close $log_search_file: $OS_ERROR\n";
    

    【讨论】:

    • 关于三个参数选项,如果我错了,请纠正我,但我的印象是在方向运算符和路径之间放置一个空格可以解决开头的可能性问题路径可能被解释为运算符的一部分。是否有任何其他问题无法通过空格分隔来解决?
    【解决方案3】:

    我看到你在这里发布了我生锈的 Perl 代码,真尴尬。 ;) 我今天早些时候对原始 PowerShell 线程中的答案进行了更新,它提供了一个更通用的解决方案,该解决方案还可以处理正则表达式元字符,并且不需要您手动转义 600 个哈希元素中的每一个:PowerShell multiple string replacement efficiency。我在您的原始问题中添加了 perlregex 标签,但我的修改尚未获得批准。

    [正如我所提到的,由于我最近一直在使用 PowerShell(哎呀,这些天我用 PowerShell 准备早餐......),我的 Perl 有点尘土飞扬,我看到它还没有消失这里没有注意到。 :P 我修复了一些我注意到在第二次查看时可以更好地编码的东西,这些都在底部注明。对于像这样的有限使用的快速和肮脏的脚本,我不会为错误消息和声明以及其他冗长而烦恼,我也不特别推荐它。正如 Perl 的座右铭所说,“让简单的事情变得简单,让困难的事情成为可能”。嗯,这是一个让事情变得简单的例子,Perl 的主要优点之一是当你尝试快速简单地做某事时,它不会强迫你“正确”。但我确实关闭了文件句柄。 ;)

    【讨论】:

      猜你喜欢
      • 2020-07-23
      • 2017-09-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多