【问题标题】:copy the previous line based on a group of line in another file using awk使用 awk 根据另一个文件中的一组行复制上一行
【发布时间】:2014-05-12 09:19:40
【问题描述】:

我有一个文件 file1,其内容为以下模式,由空行分隔的一组行。

First line

line1 
Line2

abc
def
jkl

123456
opertxt

this is line
this is sentence
this is last line

我在下面的格式中有另一个平面文件 2。 file2中的eact行对应file1中的行组。

group1
group2
group3
group4
group5

我想同时读取这两个文件并重复 file2 中的行。我将输出重定向到file3。我想要文件 3 看起来像这样。

group1
group2
group2
group3
group3
group3
group4
group4
group5
group5
group5

所以最后 file1(不包括空白行)和 file3 中的行数将相同。 有人可以建议使用 ksh 或 awk, sed 的解决方案吗?

【问题讨论】:

    标签: awk sed


    【解决方案1】:

    您可以使用这种awk 方法,首先读取file2 在数组中存储值,然后读取file1 打印相应的行:

    $ awk 'BEGIN {count=1} FNR==NR {a[++i]=$0; next} /^$/ {count++; next} {print a[count]}' f2 f1
    group1
    group2
    group2
    group3
    group3
    group3
    group4
    group4
    group5
    group5
    group5
    

    说明

    • BEGIN {count=1} 在开头将 count var 设置为 1。
    • FNR==NR {a[++i]=$0; next} 在读取file2(由FNR==NR 表示)时,将每一行的值存储在数组a[] 中。
    • /^$/ {count++; next} 读取 file1 时,每次找到空行时递增计数器。然后跳过这一行。
    • {print a[count]}file1 的其余行中,打印数组 a[] 中的行存储,并使用计数器指定的索引。

    【讨论】:

      【解决方案2】:

      Perl方案,并行读取两个文件:

      #!/usr/bin/perl
      use warnings;
      use strict;
      
      open my $LINES,  '<', 'file1' or die $!;
      open my $GROUPS, '<', 'file2' or die $!;
      
      my $group = <$GROUPS>;
      
      while (<$LINES>) {
          $group = <$GROUPS>, next if /^$/;
          print $group;
      }
      

      【讨论】:

        【解决方案3】:

        Awk 和 sed:

        sed 's/.*..*/0/;s/^$/1/' input | awk '$1{s += 1;next} {print "group"s+1;}'
        

        这里 sed 在有新组时输出为 1,否则为 0。 awk 只是计算一个运行总和。

        输出:

        group1
        group2
        group2
        group3
        group3
        group3
        group4
        group4
        group5
        group5
        group5
        

        【讨论】:

          【解决方案4】:

          这是一种计算每段行数的笨拙方法:

          awk -v RS= '
              FNR==NR {split($0,groups,/\n/); next} 
              {n = split($0,a,/\n/); for (i=1; i<=n; i++) print groups[FNR]}
          ' file2 file1
          

          【讨论】:

          • 好一个!我最初也想过类似的事情,但后来我注意到groupsN 可能只是一些示例文本,而真正的文本并不遵循这种模式。
          【解决方案5】:

          这可能对你有用(GNU sed):

          sed ':a;$!{N;ba};s/\n/\\n/g;s|.*|1{x;s/^/&/;x};/./!{x;s/[^\\n]*\\n//;x;d};G;s/[^\\n]*\\n//;P;d|' file2 | sed -f - file1
          

          从组文件中构建了一个针对文本文件运行的 sed 脚本。

          脚本将组列表附加到文本文件的每一行。然后删除文本文件行并打印列表中的第一组。遇到空行时,列表中的第一组将被删除。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-02-20
            • 1970-01-01
            • 2017-11-10
            • 2023-01-20
            相关资源
            最近更新 更多