输入文件
Cat|Dog|Dragon -40|1000|-20
K|B|L|D|E -9|1|-100|-8|9
输出文件:
Dragon 20
B 1
工作流程是这样的:在 column2 中,找到绝对值最小的索引,然后使用该索引获取 column1 中的元素。有人对此有想法吗?
使用我难以置信的感知能力,我发现了一个暗示,这并不完全是一个操作问题。可以Homework吗?
{
split($1, catdog, "|")
split($2, numbers, "|")
smallest = -1
for(i in numbers) {
a = numbers[i]
if(a < 0)
a = -a
if(smallest == -1 || a < smallest) {
smallest = a
j = i
}
}
printf("%-9s %2d\n", catdog[j], smallest)
}
perl -lnwe '($k,$v) = map [split /\|/], split;
my %a;
@a{@$k} = map abs, @$v;
print "$_\t$a{$_}" for
(sort { $a{$a} <=> $a{$b} } keys %a)[0];
' input.txt
输出:
Dragon 20
B 1
解释:
命令行开关:
-l
处理行尾,为方便起见-n
从参数文件名或标准输入读取输入编码:
最右边split
在空白处分割每一行。我们在管道上再次拆分这些字段|
并将结果放入数组 ref 中[ ... ]
,以便它们适合标量变量 ( $k
and $v
)。然后我们声明一个词法哈希%a
来保存每个新输入行的数据。我们需要这个声明来避免一行中的值泄漏到下一行。然后,我们通过散列切片将键从 分配$k
给 中的绝对值$v
。这与以下原理相同:
@foo{'a', 'b', 'c'} = (1, 2, 3); # %foo = ( a => 1, b => 2, c => 3);
然后我们对值进行哈希排序,取第一个带有下标的值,[0]
并打印出相应的键和值,并用制表符分隔。
以下awk
命令应该可以工作:
awk '
function abs(value)
{
return (value<0?-value:value)
}
{
len=split($2,arr,"|")
min=abs(arr[1])
minI=1
for(i=1;i<=len;i++){
if(abs(arr[i])<min){
min=abs(arr[i])
minI=i
}
}
split($1,arr2,"|")
print(arr2[minI],min)
}' file
输出:
Dragon 20
B 1