我有数千行,如下列表所示。
文件名=“文本文件”
3 2 3 1 4 7
5 8 6 8 9 8
8 9 4 7 3 9
2 3 4 4 9 2
2 2 0 9 4 0
0 9 8 2 4 0
我必须使用条件搜索特定元素(例如,在第五列中)。 (实际上我必须找到最大值。)我想要这个输出。第五列的最大值 = 9
线路:5 8 6 8 9 8
2 3 4 4 9 2
我使用了以下代码。
var=$(cat newfifth1 | awk 'BEGIN {max = 0} {if ($5>max) max = $5} END {print max}')
cat textfile | grep "$var" | cat $1 $2 $3 $4 $5 $6 >> newtextfile
但这不起作用!
如果可能的话请给我一个更简单的方法和使用数组的方法。
答案1
根据您问题中的数据样本,这似乎就是您想要的(否则请澄清您的问题):
awk '$5 > max { max = $5 ; out = $0 } END { print out }' datafile
这将打印数据文件中第五列中的值为最大值的行。
该程序的工作原理如下:对于每一行,第五列元素将与存储的最大值max
(最初为 0)进行比较,如果找到更大的值,则max
获取分配的值(用于后续比较),并且当前行 ( $0
) 包含最大值存储在变量 中out
。作为程序的最终操作,变量的值out
将被打印。
如果您的数据中只有小于零的值,您将需要(因为max
零的隐式初始化)一些扩展;通常max
,使用已知低于数据中的值的值显式初始化变量就足够了,例如使用BEGIN { max = -999999 }
,但您也可以使用通用代码模式,如下所示:
awk '(max==0 && max=="") || $5 > max { max = $5 ; out = $0 } END { print out }' datafile
(max==0 && max=="")
将条件部分解读为:“max
仍然未定义吗?” (即尚未分配值)。
答案2
这里有几个解决方案。
两遍(无数组):
awk '
{
if (NR == FNR) {
if ($5 > max) max = $5
} else {
if ($5 == max) print
}
}' textfile textfile
NR
是所有输入中计数的记录号(行号)。FNR
是行号在当前文件内。因此,举例来说,如果您awk
使用两个文件的输入运行:fileC
,其长度为三行, 和fileD
,其长度为四行,NR
并且FNR
将采用以下值:NR FNR 1 1 2 2 3 3 4 1 5 2 6 3 7 4
因此,测试
NR == FNR
是查看是否正在查看第一个文件的经典技巧。- 因此,上面读取输入文件两次(您是否注意到最后一行,其中
textfile
指定了两次?)。在第一遍中,如果找到最大值;在第二遍中,它打印包含该值的所有行。
一次性(使用数组):
awk '
{
if ($5 >= max) {
if ($5 > max) {
max = $5
delete result
count = 0
}
result[++count] = $0
}
}
END { for (i = 0; i <= count; i++) print result[i] }' textfile
- 这会将与最大值匹配的行存储在名为 的数组中
result
。这很棘手,因为在读完文件之前我们不知道最大值(因为我们只读取文件一次)。因此,每当我们遇到一个比我们以前见过的任何值都高的值(即,我们找到一个新的最大值)时,我们就会清除(delete
)result
数组并重新开始。 - 然后,当我们到达文件末尾时,我们打印我们找到的内容。
注意:如果第五列中的每个值都≤ 0,则上述命令将失败。要处理这种情况,请更改if ($5 >…
为if (max == "" || $5 >…
“整个”(包括if ($5 >= max)
测试)。