【问题标题】:Using Perl, how can I replace newlines with commas?使用 Perl,如何用逗号替换换行符?
【发布时间】:2010-11-10 13:40:56
【问题描述】:

我放弃了 sed,听说 Perl 更好。

我想要一个可以从 'unix' 命令行调用的脚本,并将输入文件中的 DOS 行尾 CRLF 转换为输出文件中的逗号:

喜欢

myconvert infile > outfile

infile 在哪里:

1
2
3

会导致输出文件:

1,2,3

我更喜欢带有一些最小 cmets 的更明确的代码,而不是“最短的可能解决方案”,所以我可以从中学习,我没有 perl 经验。

【问题讨论】:

    标签: regex perl


    【解决方案1】:

    在 shell 中,你可以通过多种方式做到这一点:

    cat input | xargs echo | tr ' ' ,
    

    perl -pe 's/\r?\n/,/' input > output
    

    我知道你希望它更长,但我真的不明白编写多行脚本来解决如此简单的任务的意义 - 简单的正则表达式(在 perl 解决方案的情况下)是完全可行的,这不是人为的东西缩短 - 这是我每天用来解决手头问题的代码类型。

    【讨论】:

    • 这似乎也是一个不错的解决方案。我不知道它是如此简单。我只需要用于 perl 语法的 cmets,但这只是一个正则表达式和 2 个开关,没问题:-)
    【解决方案2】:
    #!/bin/perl
    while(<>) {      # Read from stdin one line at a time
        s:\r\n:,:g;  # Replace CRLF in current line with comma
        print;       # Write out the new line
    }
    

    【讨论】:

    • 所以 s/// 隐式操作 $_ 是可以的,但 print 不能这样做?
    • 实际上这并不能满足您的要求,因为您必须在标准输入上提供文件。我将把这部分作为练习留给读者。
    • 是的,抱歉我没有正确阅读问题,我将其更改为正确的。我假设您的输入文件没有尾随 CRLF 否则这将打印 1,2,3
    • 它很容易将其转换为处理文件的东西,并且不会像(当前)接受的答案那样浪费公吨内存来完成其工作。 +1
    • 呃,这确实处理了一个文件。 &lt;&gt; 等价于 &lt;ARGV&gt;,它从 @ARGV 中的每个文件中读取文件列表或从 STDIN 中读取
    【解决方案3】:
    use strict;
    use warnings;
    
    my $infile = $ARGV[0] or die "$0 Usage:\n\t$0 <input file>\n\n";
    open(my $in_fh , '<' , $infile) or die "$0 Error: Couldn't open $infile for reading: $!\n";
    my $file_contents;
    {
    
        local $/; # slurp in the entire file. Limit change to $/ to enclosing block.
        $file_contents = <$in_fh>
    
    }
    close($in_fh) or die "$0 Error: Couldn't close $infile after reading: $!\n";
    
    # change DOS line endings to commas
    $file_contents =~ s/\r\n/,/g;
    $file_contents =~ s/,$//; # get rid of last comma
    
    # finally output the resulting string to STDOUT
    print $file_contents . "\n";
    

    您的问题文本和示例输出不一致。如果您将所有行尾都转换为逗号,则从最后一行结尾开始,您将在结尾处添加一个额外的逗号。但是您的示例仅显示数字之间的逗号。我假设您希望代码输出与您的示例匹配并且问题文本不正确,但是如果您想要最后一个逗号,只需删除带有注释“摆脱最后一个逗号”的行。

    如果有不清楚的命令,http://perldoc.perl.org/是你的朋友(右上角有一个搜索框)。

    【讨论】:

    • 那真的很浪费,没有必要把整个文件都塞进内存来查找和替换:/
    • 这不是这个特定问题的好答案,但它是一种有用的技术。
    • 我喜欢这个解决方案,但我喜欢将它实现为一个循环,这样我就可以将其设置为用户定义的字段数量(将 \n 转换为 csv 文件的逗号,但它有九个字段长...
    【解决方案4】:

    很简单:

    tr '\n' , <infile >outfile
    

    【讨论】:

      【解决方案5】:

      避免啜饮,不要在结尾添加逗号并打印出格式正确的文本文件(所有行必须以换行符结尾):

      #!/usr/bin/perl
      
      use strict;
      use warnings;
      
      my $line = <>;
      
      while ( 1 ) {
          my $next = <>;
          s{(?:\015\012?|\012)+$}{} for $line, $next;
          if ( length $next ) {
              print $line, q{,};
              $line = $next;
          }
          else {
              print $line, "\n";
              last;
          }
      }
      __END__
      

      【讨论】:

        【解决方案6】:

        就我个人而言,我会避免不得不向前看(如 Sinar 的回答)。有时你需要,但我有时在处理最后一行时做错了。

        use strict;
        use warnings;
        
        my $outputcomma = 0;  # No comma before first line
        
        while ( <> )
        {
            print ',' if  $outputcomma ;
            $outputcomma = 1 ; # output commas from now on
            s/\r?\n$// ;
            print ;
        
        }
        print  "\n" ;
        

        【讨论】:

          【解决方案7】:

          顺便说一句:在 sed 中,它将是: sed ':a;{N;s/\r\n/,/;ba}' infile &gt; outfile

          【讨论】:

            【解决方案8】:

            使用 Perl

            $\ = "\n";              # set output record separator
            $, = ',';
            $/ = "\n\n";
            
            while (<>) {
                chomp;   
                @f = split('\s+', $_);
                print join($,,@f);
            }
            

            在unix中,也可以使用awk或tr等工具

            awk 'BEGIN{OFS=",";RS=""}{$1=$1}1' file
            

            tr "\n" "," < file
            

            【讨论】:

            • 我猜反对票是因为:1)它根本没有像 OP 所说的那样解决问题(至少,我是如何阅读它的),以及 2)它似乎很严重以非常不明显的方式滥用魔法变量。
            • 我不介意投票,但至少告知问题所在,以便解决方案提供者可以改进/编辑他/她的代码以纠正错误。
            猜你喜欢
            • 1970-01-01
            • 2019-10-24
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-05-29
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多