【问题标题】:How can I make changes to only the first line of a file?如何仅更改文件的第一行?
【发布时间】:2010-10-07 14:22:30
【问题描述】:

我想知道我可以在 sed 中使用哪种模式来更改大文件 (~2 GB) 的第一行。偏爱 sed 只是因为我认为它必须比 Python 或 Perl 脚本快。

文件具有以下结构:

field 1, field 2, ... field n
data

并且,考虑到每个字段的标识符中都有空格的可能性,我需要用这种方式用下划线替换每个空格:

**BEFORE** 
the first name,the second name,the first surname,a nickname, ...
data

**AFTER**
the_first_name,the_second_name,the_first_surname,a_nickname, ...
data

任何指向要使用的正确模式的指针,或其他脚本解决方案都会很棒。

【问题讨论】:

    标签: perl scripting file sed


    【解决方案1】:

    您不太可能注意到 Perl、Python、 和 sed。您的脚本将花费大部分时间等待 IO。

    如果行的长度相同,则可以就地编辑,否则 将不得不创建一个新文件。

    在 Perl 中:

    #!/usr/bin/env perl
    use strict;
    
    my $filename = shift;
    open my $in_fh, '<', $filename
      or die "Cannot open $filename for reading: $!";
    my $first_line = <$in_fh>;
    
    open my $out_fh, '>', "$filename.tmp"
      or die "Cannot open $filename.tmp for writing: $!";
    
    $first_line =~ s/some translation/goes here/;
    
    print {$out_fh} $first_line;
    print {$out_fh} $_ while <$in_fh>; # sysread/syswrite is probably better
    
    close $in_fh;
    close $out_fh;
    
    # overwrite original with modified copy
    rename "$filename.tmp", $filename
      or warn "Failed to move $filename.tmp to $filename: $!";
    

    【讨论】:

    • 嗨,你能解释一下为什么只有第一行存储在$first_line中吗?
    【解决方案2】:

    您提到的更改(用下划线替换每个空格)不会更改行的长度,因此理论上可以就地完成。

    警告!:未经测试!

    head -n 1 yourfile | sed -e 's/ /_/g' > tmpfile
    dd conv=nocreat,notrunc if=tmpfile of=yourfile
    

    我不太确定conv=... 参数,但它似乎应该使dd 用转换后的行覆盖原始文件的开头。

    请注意,如果您想进行任何其他可能改变行长的转换,请不要,不要这样做。你必须做一个完整的副本。像这样:

    head -n 1 yourfile | sed -e 's/ /_/g' > tmpfile
    tail -n + 2 | cat tmpfile - > transformedfile
    

    【讨论】:

      【解决方案3】:

      编辑前 10 行

      sed -i -e '1,10s/ /_/g'
      

      在 Perl 中,您可以在标量上下文中使用触发器运算符:

      perl -i -pe 's/ /_/g if 1 .. 10'
      

      【讨论】:

      • 那 re 需要一个 g 在末尾,以使其替换行中的所有空格,而不仅仅是第一个。
      • perl -i -pe 's/ /_/g if 1 .. 10' ???哇,我从未听说过“if 1..10”中的这种语法。有时我对 Perl 有点恼火。为什么所有这些例外?为什么不使用简单的 if($.
      • @dehmann 它是一个触发器运算符,参见perldoc.perl.org/perlop.html 非常方便
      • 虽然有可能得到答案,但为什么这实际上没有提到如何只更改第一行,正如问题所问的那样?由于缺乏更好的方法,我求助于: perl -i -pe 's| ||g 如果 1 .. 1'
      【解决方案4】:

      我认为您不想使用任何需要将数据写入新文件的解决方案。

      如果您非常确定只需将大文本文件的第一行中的空格更改为下划线,您只需阅读第一行,交换字符并将其写回原处:

      #!/usr/bin/env perl
      use strict;
      
      my $filename = shift;
      open (FH, "+< $filename") || die "can't open $filename: $!";
      my $line = <FH>;
      $line =~ s/ /_/g;
      seek FH, 0, 0; # go back to the start of the file
      printf FH $line;
      close FH;
      

      要使用它,只需传递要更新的文件的完整路径:

      # fixheader "/path/to/myfile.txt"
      

      【讨论】:

      • 那个打开 || die 不正确,它评估为打开 FH,("+
      • 这也是我的解决方案。 +1
      【解决方案5】:

      这可能是一个解决方案:

      use Tie::File; tie my @array,"Tie::File","path_to_file"; $array[0] = "new text"; untie @array;

      Tie::File是我用得最多的模块之一,使用起来非常简单。数组中的每个元素都是文件中的一行。然而,缺点之一是这会将整个文件加载到内存中。

      【讨论】:

      • 实际上如果不需要,它不会加载文件,所以如果你只更改第一行并且字符数没有改变,这不会有太大的开销。跨度>
      • 我认为在一行修改之后出现相同数量的字符是非常罕见的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-24
      • 2019-08-21
      • 2020-07-04
      • 1970-01-01
      • 2015-09-23
      • 2012-02-21
      相关资源
      最近更新 更多