2016-08-29 14 views
0

我有一个很简单的问题,但是我觉得很难解决这个问题。 我有两个相当长的数据列,我想分成几列。脚本应该开始写入数据到一个新的列,每次它发现在第一列中的特定的字符串: 输入:每当你看到一个模式时,将一列分成几列

A B 
1 C 
2 C 
3 C 
4 C 
A D 
1 D 
2 D 
3 D 
4 D 

输出:

A B A D 
1 C 1 D 
2 C 2 D 
3 C 3 D 
4 C 4 D 

(分离图案是A)

回答

1

AWK用浆糊:

$ awk '$1 == "A" { ++n } { print > ("t.tmp." n) }' input.txt 
$ ls t.tmp.* 
t.tmp.1 t.tmp.2 
$ paste t.tmp.* 
A B  A D 
1 C  1 D 
2 C  2 D 
3 C  3 D 
4 C  4 D 

编辑

更高效(只能建文件一次为每个组),更健壮(避免打开的文件太多的机会,通过关闭他们,因为我们去)---感谢,埃德莫顿:

awk '$1 == "A" { close(out); out = "t.tmp." ++n} { print > out }' input.txt 

(上面假设第一条记录包含模式。如果没有,可以在BEGIN块初始化出)

+1

同意,@EdMorton,答案与改进的版本更新。我还从文档中看到,用与不打开的文件相对应的参数来调用close是无害的,在这种情况下很好理解。 – jas

1

为此,您可以使用单awk

awk 'NR>1 && /^A/{p=1} {if (p) print a[++i], $0; else a[NR]=$0}' OFS='\t' file 

A B  A D 
1 C  1 D 
2 C  2 D 
3 C  3 D 
4 C  4 D 
+1

不错,不需要复杂。现在编辑。 – anubhava

-2

如果你正在读这篇文章,想知道为什么它得到downvoted,这只是一些小丑幼稚因为我指出了一些问题,以及他们可以改进他们以前的答案的方式,downvote与这个答案的技术优点无关。这是惯用awk解决这个问题的方法。

$ awk -v OFS='\t' ' 
    $1 == "A" { numRows=0; ++numCols } 
    { val[++numRows,numCols] = $0 } 
    END { 
     for (rowNr=1;rowNr<=numRows;rowNr++) { 
      for (colNr=1;colNr<=numCols;colNr++) { 
       printf "%s%s", val[rowNr,colNr], (colNr<numCols ? OFS : ORS) 
      } 
     } 
    } 
' file 
A B  A D 
1 C  1 D 
2 C  2 D 
3 C  3 D 
4 C  4 D 
-1

使用GNU AWK多记录 - 适用于任何数量的模式的出现 - 假定相等长度列

pat=A 
awk -vpat=$pat -F'\n' ' 
BEGIN {RS="(^|\n)"pat" "} 
NR>1{ 
    nr=NR-2 
    fld[nr][0]=pat" "$1 
    for(i=2; i<=NF; ++i) 
    fld[nr][i-1]=$i 
} 
END { 
    for(i=0; i < NF; ++i) { 
    for(j=0; j < NR-1; ++j) 
     printf("%s%s", j?"\t":"", fld[j][i]) 
    printf("\n") 
    } 
} 
' 

输入

A B 
1 C 
2 C 
3 C 
4 C 
A D 
1 D 
2 D 
3 D 
4 D 
A X 
1 X 
3 X 
5 X 
7 X 

输出

A B  A D  A X 
1 C  1 D  1 X 
2 C  2 D  3 X 
3 C  3 D  5 X 
4 C  4 D  7 X 
0

使用csplitpaste

$ csplit -zsf file infile.txt '/A/' {*} 
$ paste file* 
A B  A D 
1 C  1 D 
2 C  2 D 
3 C  3 D 
4 C  4 D 

man csplit

csplit可 - 文件分割成由上下文行确定

-z,部分--elide-空文件 删除空输出文件

-s,--quiet,--silent 不打印输出文件大小的计数

-f,--prefix = PREFIX 使用前缀,而不是 'XX'

{*}多次重复以前的模式尽可能