创建类别(如果不存在),如果存在,则打印当前数据

时间:2016-06-29 07:13:21

标签: bash awk

我有一些带有类别行的文本文件和每个类别的数字数据。虽然类别数量有限,例如 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,也不胜感激。

感谢。

3 个答案:

答案 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]ab[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