【问题标题】:sed delete 1st line and remove leading/trailing white spacessed 删除第一行并删除前导/尾随空格
【发布时间】:2013-09-23 16:17:41
【问题描述】:

我正在尝试使用 sed 删除第一行并删除后续行中的前导和尾随空格

如果我有类似的东西

第1行 线2 第 3 行

应该打印出来

线2 第 3 行

所以我在 unix shell 上尝试了这个命令:

sed '1d;s/^ [ \t]*//;s/[ \t]*$//' file.txt

它按预期工作。

当我在我的 perl 脚本中尝试相同的操作时:

my @templates = `sed '1d;s/^ [ \t]*//;s/[ \t]*$//' $MY_FILE`;

它给了我这个消息“sed: -e expression #1, char 10: unterminated `s' command”并且不打印任何东西。谁能告诉我哪里出错了

【问题讨论】:

  • IIRC,你需要在 perl 中转义 $s。
  • 是的,我试过了。仍然给我同样的错误并且什么也不打印

标签: regex perl sed


【解决方案1】:

反引号的作用类似于双引号。 Perl 会在其中插入变量,正如您已经知道的那样,因为您使用了$MY_FILE。你可能不知道$/实际上是一个variable,即输入记录分隔符(默认为换行符)。制表符之前的反斜杠也是如此。这里 Perl 将为您解释 \t 并将其替换为制表符。您需要第二个反斜杠,以便 sed 看到 \t 而不是实际的制表符。不过,后者也可能有效。

【讨论】:

    【解决方案2】:

    您的表达有误。您需要在 2 个替换语句之间使用分号。您应该改用以下内容:

    my @templates = `sed '1d;s/^ [ \\t]*//;s/[ \\t]*\$//' $MY_FILE`;
    

    按照其他答案中的建议转义 $\。我应该注意,它也适用于我而无需转义 \,因为它已被文字标签取代。

    【讨论】:

      【解决方案3】:

      考虑使用安全管道打开而不是反引号,以避免转义问题。例如:

      my @templates = do {
          open my $fh, "|-", 'sed', '1d;s/^ [ \t]*//;s/[ \t]*$//', $MY_FILE
              or die $!;
          local $/;
          <$fh>;
      };
      

      【讨论】:

        【解决方案4】:

        你为什么要从 Perl 调用 Sed?用等效的 Perl 代码替换 sed 只是几个精心策划的击键。

        my @templates;
        if (open (M, '<', $MY_FILE)) {
            @templates = map { s/(?:^\s*|\s*$)//g; $_ } <M>;
            shift @templates;
            close M;
        }  else { # die horribly? }
        

        【讨论】:

          【解决方案5】:

          正如其他人所提到的,我建议您仅在 Perl 中或仅在 Sed 中执行此操作,因为确实没有理由将两者都用于此任务。在 Perl 中使用 Sed 意味着您必须担心以某种方式转义、引用和捕获输出(除非从管道读取)。显然,所有这些都使事情变得复杂,并且也使代码非常难看。

          这是一个 Perl 单行代码,可以处理您的重新格式化:

          perl -le 'my $line = <>; while (<>) { chomp; s/^\s*|\s*$//; print $_; }' file.txt
          

          基本上,您只需获取第一行并将其存储在一个不会使用的变量中,然后处理其余的行。下面是一个小脚本版本,您可以将其添加到现有脚本中。

          #!/usr/bin/env perl
          
          use strict;
          use warnings;
          
          my $usage = "$0 infile";
          my $infile = shift or die $usage;
          
          open my $in, '<', $infile or die "Could not open file: $infile";
          
          my $first = <$in>;
          
          while (<$in>) {
              chomp;
              s/^\s*|\s*$//;
          
              # process your data here, or just print...
              print $_, "\n";
          }
          close $in;
          

          【讨论】:

            【解决方案6】:

            这也可以通过awk 关闭

            awk 'NR>1 {$1=$1;print}' file
            line2
            line3
            

            【讨论】:

              猜你喜欢
              • 2012-02-28
              • 2017-03-16
              • 1970-01-01
              • 2012-05-24
              • 2011-05-25
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多