1

给定一个包含项目信息的制表符分隔的文本文件:

41850 0.4 0.5 LG EN RP 比利制造冰箱,标准
朋友       
9338 0.4 0.5 LG EN RP 闪耀,音乐剧!芥末,上校   
7255 0.5 0.5 LG EN RP 你能扮演杜鲁门吗,哈丽特
犹太人的竖琴
9314 0.5 0.5 LG EN RP 嗨,Skippy Plum,教授   

请注意其中两行的“孤立”标题。使用 awk,如何将这个孤儿合并回上面的标题字段?

伪awk:

awk '/^[[:digit:]]/{getline; ??? 
    if next line ~ /^[[:alpha:]]/ title=$7 + previous
    END{print $0}' <FILE

无论如何,步骤似乎是:

任何一个

  • 找到“正常”行,
  • 测试以下行是否为“孤儿”
  • 如果是这样,将“孤儿”附加到字段 7 [标题字段],
  • 打印线

或者

  • 寻找“孤儿”
  • 以某种方式附加到上一行的字段 7 [永远不会有两个连续的孤儿]

第一种方法对我来说似乎最简单——但是,我是这里的无知者。

4

3 回答 3

2
$ tac file | awk 'BEGIN{FS=OFS="\t"} NF==1{s=" "$0;next} {$7=$7 s; s=""}1' | tac
41850   0.4     0.5     LG      EN      RP      Billy Makes a Friend    Fridgewell, Norm
9338    0.4     0.5     LG      EN      RP      Shine, The Musical!     Mustard, Colonel
7255    0.5     0.5     LG      EN      RP      Can You Play the Jew's Harp     Truman, Harriet
9314    0.5     0.5     LG      EN      RP      Hi, Skippy      Plum, Prof

这是一种不使用 tac 并使用 GNU awk 的替代方法(只需将 gensub() 替换为 2 个 sub() 调用或 match() 或其他任何您不想使用 gawk 的方法):

$ cat tst.awk
BEGIN { FS="\t" }
NF==1 { s = gensub(/([^\t]+[\t]){6}[^\t]+/, "\\0 "$1, "", s); next }
      { printf "%s",s; s=$0 ORS }
END   { printf "%s",s }

$ gawk -f tst.awk file
41850   0.4     0.5     LG      EN      RP      Billy Makes a Friend    Fridgewell, Norm
9338    0.4     0.5     LG      EN      RP      Shine, The Musical!     Mustard, Colonel
7255    0.5     0.5     LG      EN      RP      Can You Play the Jew's Harp     Truman, Harriet
9314    0.5     0.5     LG      EN      RP      Hi, Skippy      Plum, Prof
于 2012-10-27T05:34:40.930 回答
2

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

sed '$!N;/\n\([^\t]*\t\)\{7\}/!s/\(\t[^\t]*\)\n\(.*\)/ \2\1/;P;D' file
于 2012-10-27T11:47:51.197 回答
1

我意识到这个问题被标记了awk,但这可能是使用 Perl 更容易的时候之一:

perl -F"\t"  -lane 'BEGIN { $, = "\t" } 
            if (/^\d{2}/) { print @saved if @saved; @saved = @F } 
                     else { $saved[6].=" $_" }; 
                      END { print @saved }' foo.txt 

虽然这是相同想法的 awk 版本(通过 Ed Morton 进行了一些改进):

awk -F"\t" '/^[0-9][0-9]/  { if (prefix) { print prefix"\t"title"\t"suffix }
                             prefix=$1
                             for ( i=2; i<=6; ++i ) prefix=prefix"\t"$i
                             title=$7; suffix=$8
                             next } 
                           { title = title" "$0 } 
                       END { print prefix"\t"title"\t"suffix }' foo.txt 

这两个脚本都给了我这个输出,看起来像你想要的:

41850   0.4     0.5     LG      EN      RP      Billy Makes a Friend    Fridgewell, Norm 
9338    0.4     0.5     LG      EN      RP      Shine, The Musical!     Mustard, Colonel
7255    0.5     0.5     LG      EN      RP      Can You Play the Jew's Harp     Truman, Harriet
9314    0.5     0.5     LG      EN      RP      Hi, Skippy      Plum, Prof
于 2012-10-27T02:46:02.980 回答