我有一个像这样的文件示例:
2931
7895
6688
7895
2931
2931
6688
我想生成一个包含此列和另一列的文件,如下所示:
2931 1
7895 2
6688 3
7895 2
2931 1
2931 1
6688 3
答案1
您需要为每种新类型的内容指定一个编号,然后在具有相同内容的每一行上显示该编号?
awk '
{ if ( !seen[$0]++ ) {
ind++ ; n[$0]=ind
}
}
{ print $0, n[$0] }
'
做你需要的
使用埃德·莫顿的建议可以简化并使其更像“awk”,如下所示:
awk '
! ($0 in n) { n[$0]=++ind }
{ print $0, n[$0] }
'
答案2
假设您希望第二列成为第一列中每个数字的唯一数字(问题中不清楚):
$ awk '$2 = ( (k = key[$1]) ? k : key[$1] = ++n )' file
2931 1
7895 2
6688 3
7895 2
2931 1
2931 1
6688 3
这会跟踪 中最近分配的数字n
,以及关联数组 中第一列和生成的数字(“键”)之间的关联key
。该变量只是一个非常小的优化,以避免在第一列中存在数字的情况下k
取消引用两次。key
逻辑:
$1
如果对应的键$2
不为零,则分配对应的键(零表示未初始化,并且$1
以前从未见过)。如果为零,则将下一个可用数字分配给该键,然后分配给该键$2
我们不需要明确print
任何内容,因为表达式的结果将不为零。由于表达式的结果非零,因此它会触发默认操作,即打印当前(修改后的)记录。
该命令的一个稍微更通用的变体将使用整行作为值,然后在末尾添加一个新列,无论输入数据中存在多少列:
awk '$(NF+1) = ( (k = key[$0]) ? k : key[$0] = ++n )' file
用等效的“长手”语法拼写出代码:
awk '
{
k = key[$0]
if (k != 0)
newval = k
else
newval = key[$0] = ++n
print $0, newval
}' file