将“块前缀”添加到属于文件同一块的所有行

将“块前缀”添加到属于文件同一块的所有行

我试图使标题尽可能具体,一个例子应该可以解决问题。

我有一个制表符分隔的文件,其中的行以1to开头5。这被视为一个块(每个块可以有多个4和条目5)。

  • next1定义下一个块的开始,依此类推。
  • 我的前缀总是在以 开头的行中3。我想在每个块的每一行的开头写下这个词。

任何有关如何解决此问题的想法将不胜感激。不一定是sed,可以是awk,但sed会是首选。

  • 输入文件示例
    1 foo1
    2 foo1
    3 bar1 | Prefix block 1
    4 foo1
    5 foo1
    1 foo2
    2 foo2
    3 bar2 | Prefix block 2
    4 foo2
    4 foo3
    5 foo2
    5 foo3
    
  • 此输入示例所需的输出
    bar1 1 foo1
    bar1 2 foo1
    bar1 3 bar1
    bar1 4 foo1
    bar1 5 foo1
    bar2 1 foo2
    bar2 2 foo2
    bar2 3 bar2
    bar2 4 foo2
    bar2 4 foo3
    bar2 5 foo2
    bar2 5 foo3
    

答案1

在您的情况下,想到了两遍awk解决方案(这意味着我们必须指定输入文件名两次作为命令行上的操作数)。它假设该行上的标记由 on 输入分隔\t,并且也由 on 输出分隔\t

awk 'BEGIN{FS=OFS="\t"}
     NR==FNR{if ($1=="3") pre[++i]=$2;next} $1=="1" {j++} {print pre[j],$0}' input input

在第一遍中,NR(全局行计数器)等于FNR(每个文件行计数器),pre每次遇到第一个字段 ( $1) 等于 的行时,我们都会用前缀填充数组3。因此,pre是“块号”和关联前缀之间的映射。除此之外,我们不打印任何内容并立即跳到下一行执行。

在第二遍中,j每次找到“起始块”条件(第一个字段$1等于1)时,我们都会增加块计数器,并且对于所有行都在前面添加与块计数器相对应的前缀。

答案2

GNU sed在扩展正则表达式模式下运行-E并关闭自动打印-n,以便我们知道何时打印。

sed -En '
  #--------------------------------
  # printing the block in pattern space
  #--------------------------------
  /\n/{
    s/.*\n(.*)/\1&/
    P;/\n.*\n/D;$d;g
  }

  #--------------------------------
  # collect block
  #--------------------------------

  :15
  /^1/{
    N;h
    /\n5/!b15

    #--------------------------------
    # collect trailing 5 lines
    #--------------------------------
    :tail5
      $bend
      n
    /^5/{H;$!btail5;}

    #--------------------------------
    # place block prefix @ eol
    #--------------------------------
    $!x;$g
    :end
    s/.*\n3\t([^\n]+)\n.*/\n&\n\1\t/
    D; # take me to block print section
  }
' file

结果:

bar1    1   foo1
bar1    2   foo1
bar1    3   bar1
bar1    4   foo1
bar1    5   foo1
bar2    1   foo2
bar2    2   foo2
bar2    3   bar2
bar2    4   foo2
bar2    4   foo3
bar2    5   foo2
bar2    5   foo3

相关内容