我有一些带有类别行的文本文件和每个类别的数字数据。虽然类别数量有限,例如 a 到 g ,但并非所有文件都包含所有类别,例如:
文件1:
a 199
b 20
c 70
e 1
f 200
file2的:
a 11
b 103
c 232
d 92
f 7
g 201
file3的:
a 100
b 120
c 9
d 20
e 33
f 123
g 9191
我想生成输出文件,如果该类别已经存在,则会再现该行,但如果该类别不存在,则使用数字数据0创建该类别。我想使用
$ awk '$1 ~ /category/ {print $0}'
对于已经存在的类别,但我不确定如何引入新的类别。
任何解决方案,即使不在awk
,也不胜感激。
感谢。
答案 0 :(得分:1)
以file1
为例:
$ awk '{a[$1]=$2} END{split("abcdefg",b,//); for (i in b) print b[i],a[b[i]]+0}' file1
a 199
b 20
c 70
d 0
e 1
f 200
g 0
a[$1]=$2
对于读取的每一行,我们将值保存在关联数组a
中的列中,并将类别(第1列)作为键。
END{split("abcdefg",b,//); for (i in b) print b[i],a[b[i]]+0}
在我们读完文件后,我们创建了一个数组b
,其中包含所有类别的值。因此b[1]
为a
而b[3]
为c
等。
接下来,对于b
中的每个元素,我们打印出数组a
中保存的值。如果a
中没有保存任何值,则awk会为我们提供默认值。为了确保默认值为零,而不是空字符串,我们将0
添加到a
中的值,这会强制awk将a
中的值视为数字。
让我们考虑一下这个测试文件:
$ cat file2
category1 1
category2 2
现在,让我们根据三个类别进行分析:
$ awk '{a[$1]=$2} END{split("category1_category2_category3",b,"_"); for (i in b) print b[i],a[b[i]]+0}' file2
category1 1
category2 2
category3 0
答案 1 :(得分:1)
我们假设您还有一个包含类别的文件:
$ cat categories
a
b
c
d
e
f
g
我们还假设所有类别都是没有空格的简单单词,并且所有文件都在类别列中排序。 编辑:实际上,任何类别字符串都会出现,但您最好使用标签或逗号等分隔符或文件中的内容,在这种情况下,将-t ","
添加到文件中下面的join
命令(如果你使用逗号)。 请参阅答案的结尾。
然后这解决了你的问题:
$ join -a 1 -o 1.1,2.2 -e 0 categories file1
a 199
b 20
c 70
d 0
e 1
f 200
g 0
join
实用程序对两个文件的第一列(默认情况下)执行关系连接操作。在这里,我们使用categories
文件和第一个示例文件来提供它。
-a 1
选项说"从第一个输入文件(categories
)中提取所有行,即使它们与第二个文件中的行不匹配(file1
)"
-o 1.1,2.2
选项说"我希望看到第一个文件中的第1列,以及输出中第二个文件中的第2列"。
-e 0
选项说明"用0
"替换所有缺失的值。
编辑:请记住,join
的两个输入文件必须在我们用于执行连接的字段上排序(第一个字段)在这种情况下的所有文件,因此每个文件上都会有一个简单的sort -o file file
。如果文件没有排序,那么join
需要将它们读入内存,就像许多其他Unix工具一样,这不是它的实现方式。相反,它是一种内存高效且快速的工具,只对输入数据提出了更严格的要求。其他工具(sort
)可以轻松处理这些限制。这是Unix philosophy的实际效果。
编辑:多字类别示例:
$ cat categories
a category
b nice
c at
d cide
e ffective
f ull of gas
g one
$ cat file1
a category,199
b nice,20
c at,70
e ffective,1
f ull of gas,200
$ join -t "," -a 1 -o 1.1,2.2 -e 0 categories file1
a category,199
b nice,20
c at,70
d cide,0
e ffective,1
f ull of gas,200
g one,0
答案 2 :(得分:0)
如果您想保留订单:
awk 'BEGIN{
split("a b c d e f g",p);
i=1
}
p[i]!=$1{
print p[i],0;
i++
}
{
i++;
print
}
END{
for (j=i;j<=7;j++)print p[j],0
}' file