Input file tab separated:
A |B | C | KEY | D| E| F |G | H | I | J | k |
----|----|----|------|---|---|-----|------|---|---|-----|-----|
word|word|word| one | 8| 8|qw123| "" | ""| ""| word| word|
word|word|word| one | 8| 8|qw234| "" | ""| ""| word| word|
word|word|word| one | 8| 8|qw111| er432| ""| ""| word| word|
word|word|word| seven| 8| 8|tr123| "" | ""| ""| word| word|
word|word|word| seven| 8| 8|ww000| "" | ""| ""| word| word|
Desired Output:
A |B | C | KEY |D |E |F |G |H |I |J |K |
----|----|----|------|--|--|-----|-----|-----|-----|----|----|
word|word|word|one | 8| 8|qw123|qw234|qw111|er432|word|word|
word|word|word|one | 8| 8|qw123|qw234|qw111|er432|word|word|
word|word|word|one | 8| 8|qw123|qw234|qw111|er432|word|word|
word|word|word|seven | 8| 8|tr123|ww000|"" |"" |word|word|
word|word|word|seven | 8| 8|tr123|ww000|"" |"" |word|word|
它是将 [F 到 I] 列的范围与相同的 KEY 合并。在 AWK 中不使用数组是否可以实现此目的?如何控制键列的值何时更改?
答案1
我不明白如何在 Awk 中不使用数组来做到这一点。在 Gawk 中会更方便,它允许数组元素是数组,但使用普通的 Awk 模拟多维数组就很容易做到。
基本上,我们需要记住输入行,然后在密钥更改时输出它们(使用更新的 FI 字段)。我们还需要在文件末尾执行此操作。为了方便起见,我们使用输出函数,因为它不可避免地会从两个地方调用。
以下使用固定列号:1-6 和 11-12 为标准数据字段,其中 4 为关键字段,7-10 为合并字段,我将其称为标签,因为需要更好的名称。这不是很好的风格,可能应该将其分解为一些变量。
awk -F '\t' '
function show_and_reset( i, c) {
for (i = 1; i <= count; ++i) {
for (c = 1; c <= 6; ++c) printf "%s\t", data[i,c]
for (f in tags) printf "%s\t", f;
for (c = ntags; c <= 3; ++c) printf "\t"
for (c = 11; c <= 12; ++c) printf "\t%s", data[i,c]
print ""
}
/* Clear the holding data */
for (f in tags) delete tags[f]
ntags = 0;
count = 0
}
/* Record one line of data */
function record( c) {
++count;
for (c = 1; c <= 6; ++c) data[count,c] = $c
for (c = 11; c <= 12; ++c) data[count,c] = $c
for (c = 6; c <= 10; ++c)
if ($c != "" && !tags[$c]++) ++ntags;
}
$4 != key { show_and_reset(); key = $4; }
{ record(); }
END { show_and_reset(); }
'