【问题标题】:Awk or Sed: File Annotationawk 或 Sed:文件注释
【发布时间】:2011-01-06 15:59:09
【问题描述】:

你好,我的朋友,我的问题是:

说明:将FILE_2的字段注释到FILE_1的对应位置。
字段分隔符对标记并因此被识别。

在我知道 awk 和 sed 之前,我在 python 中完成了这项工作,代码只有几百行。 现在我想看看 awk 和 sed 有多么强大和高效。 请给我看一些 awk 或 sed 的杰作!

分隔符对可以在 FILE_3 中配置,但我们假设一对中的第一个分隔符是
'Marker (number i) start',另一个是
'Marker (number i) done'

示例:
|-----------------FILE_1-----------------|
文字文字文字
文本 blabla
Marker_1_start
Marker_1_done
任何文字
在 blabla
Marker_2_start
Marker_2_done
文字文字

|-----------------FILE_2-----------------|
Marker_1_start强>
11
1111
Marker_1_done
Marker_2_start
2222
22
Marker_2_done

预期输出:
|-----------------FILE_Out-----------------|
文字文字文字
文本 blabla
Marker_1_start
11
1111
Marker_1_done
任何文字
在 blabla 之间
Marker_2_start
2222
22
Marker_2_done
文字文字

【问题讨论】:

  • “星号”是什么意思?我没有输入任何星号。

标签: sed awk


【解决方案1】:
awk '
    FNR==NR && /Marker_.*_done/  {sep = ""; next}
    FNR==NR && /Marker_.*_start/ {marker = $0; next}
    FNR==NR {marker_text[marker] = marker_text[marker] sep $0; sep = "\n"; next}
    1 {print}
    /Marker_.*_start/ {print marker_text[$0]}
' file_2 file_1

【讨论】:

  • @SiegeX,打印语句需要按特定顺序排列,以便标记开始在标记正文之前输出。 @Dennis,是的。
  • @Dennis: 或者{print} 是多余的,选择吧!
【解决方案2】:

有几种方法可以解决这个问题。我假设FILE_2 小于FILE_1 并且大小合理。

#!/usr/bin/awk -f
FNR == NR {
    if ($0 ~ /^Marker.*start$/) {
        flag = 1
        idx = $0
        next
    }
    if ($0 ~ /^Marker.*done$/) {
        flag = 0
        nl = ""
        next
    }
    if (flag) lines[idx] = lines[idx] nl $0
    nl = "\n"
    next
}
{
    print
    if (lines[$0]) print lines[$0]
}

运行它:

./script.awk FILE_2 FILE_1

【讨论】:

  • 你应该使用idx = $0,因为你以后使用lines[$0]。如果他的标记文本包含空格,您的代码将按原样中断。无论如何,感谢您的串联想法,我一定会从现在开始使用它,所以 +1
  • 丹尼斯,我觉得你一针见血!出色的!
    顺便说一句,SiegeX 使用 ide=$0 是对的。
【解决方案3】:

现在我想看看有多强大 高效的awk和sed可以

对于这类问题,效率很高。我确信我的代码可以进一步减少。

#!/bin/bash

awk '
  FNR == NR {
     if ($0 ~ /Marker_1_start/){m1=1;next}
     if ($0 ~ /Marker_2_start/){m2=1;next}
     if ($0 ~ /Marker_1_done/){m1=0}
     if ($0 ~ /Marker_2_done/){m2=0}

     if(m1){a[i++]=$0}
     if(m2){b[j++]=$0}
  }
  FNR != NR {
     if ($0 ~ /Marker_1_start/){print;n1=1}
     if ($0 ~ /Marker_2_start/){print;n2=1}
     if ($0 ~ /Marker_1_done/){n1=0}
     if ($0 ~ /Marker_2_done/){n2=0}

     if(n1)
       for (k = 0; k < i; k++)
         print a[k]
     else if(n2)
       for (l = 0; l < j; l++)
         print b[l]
     else
       print
  }'  ./file_2 ./file_1

输出

$ ./filemerge.sh
text text text
text blabla
Marker_1_start
11
1111
Marker_1_done
any text
in between blabla
Marker_2_start
2222
22
Marker_2_done
text text

【讨论】:

  • @Dennis 他没有被邀请参加聚会
猜你喜欢
  • 2016-01-08
  • 1970-01-01
  • 1970-01-01
  • 2017-04-23
  • 2015-10-19
  • 2015-03-19
  • 2014-06-08
  • 1970-01-01
相关资源
最近更新 更多