我有一个很简单的问题,但是我觉得很难解决这个问题。 我有两个相当长的数据列,我想分成几列。脚本应该开始写入数据到一个新的列,每次它发现在第一列中的特定的字符串: 输入:每当你看到一个模式时,将一列分成几列
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)
我有一个很简单的问题,但是我觉得很难解决这个问题。 我有两个相当长的数据列,我想分成几列。脚本应该开始写入数据到一个新的列,每次它发现在第一列中的特定的字符串: 输入:每当你看到一个模式时,将一列分成几列
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)
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块初始化出)
为此,您可以使用单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
不错,不需要复杂。现在编辑。 – anubhava
如果你正在读这篇文章,想知道为什么它得到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
使用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
使用csplit
和paste
$ 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'
{*}多次重复以前的模式尽可能
同意,@EdMorton,答案与改进的版本更新。我还从文档中看到,用与不打开的文件相对应的参数来调用close是无害的,在这种情况下很好理解。 – jas