我有一个2列文本文件,该文件按第2列(数字,升序)排序,我试图通过计算落入设置区域内的行数来进行总结。设置为1000。本质上将读取文本文件,如果第2列中的数字介于0和1000之间,则在输出文件中将有一个新行对此进行计数,然后是输出文件的第二行我将拥有1000-2000区域,依此类推,直到读取文件末尾。
不幸的是,我已经传递的代码错过了第一行输出0-1000,并且没有正确输出数学运算……我认为它忽略了INPUT文件的第一行吗?我不知道更改有多么容易,或者是否有更优雅的书写方式...
据我了解,AWK命令说
但是我的第一个区域1000不见了
输入文件:已排序并以制表符分隔
aaaaa 675
aaaaa 678
aaaaa 989
aaaaa 1001
aaaaa 1500
aaaaa 2020
...
awk -F'\t' 'BEGIN{x=0;y=1000;}{
if ($2 >= 0 && $2 < y) {x=x+1;}
else {OFS="\t"; $2=y; $3=y+1000; $4=x; print$1,$2,$3,$4; x=0; y=y+1000}
}' INput.txt > OUTput.txt
所以,我期待着:
aaaaa 0 1000 3
aaaaa 1000 2000 2
aaaaa 2000 3000 1
...
但是我得到的是
aaaaa 1000 2000 3
aaaaa 2000 3000 1
aaaaa 3000 4000 0
...
给定输入文件,这是不正确的。
(...表示文件的其余部分)
答案 0 :(得分:3)
除了@JamesBrown's answer,这是一个有效的版本:
awk '
BEGIN {
FS=OFS="\t"
}
{
while(c<$2) {
if(c)
print $1,c-1000,c,n
n=0
c+=1000
}
n++
}
END {
print $1,c-1000,c,n
}' file
给出示例输出:
aaaaa 0 1000 3
aaaaa 1000 2000 2
aaaaa 2000 3000 1
答案 1 :(得分:1)
让我们添加一些调试信息,请参见:
$ cat foo.awk
BEGIN {
OFS="\t" # moved
x=0
y=1000
}
{
printf "DEBUG NR=%d $2=%d y=%d\n",NR,$2,y > "/dev/stderr" # added
if ($2 >= 0 && $2 < y)
x=x+1
else {
$2=y
$3=y+1000
$4=x
print$1,$2,$3,$4
x=0
y=y+1000
}
}
运行它:
$ awk -f foo.awk file
DEBUG NR=1 $2=675 y=1000
DEBUG NR=2 $2=678 y=1000
DEBUG NR=3 $2=989 y=1000
DEBUG NR=4 $2=1001 y=1000
aaaaa 1000 2000 3
DEBUG NR=5 $2=1500 y=2000 # if (1500 >= 0 && 1500 < 2000) {x=x+1} ie no print
DEBUG NR=6 $2=2020 y=2000
aaaaa 2000 3000 1
答案 2 :(得分:0)
在大多数情况下,您可以在awk中将if
语句转换为模式,从而使脚本更易于理解,同时更加简洁。我对这个问题的解决方法是在名为 count.awk :
BEGIN {
threshold = 1000
FS = OFS = "\t"
}
$2 > threshold {
print first, threshold - 1000, threshold, count
threshold += 1000
count = 0
}
{
first = $1
count++
}
END {
print first, threshold - 1000, threshold, count
}
BEGIN
模式很简单:在这里我声明阈值和定界符$2 > threshold
)的那些行,我打印出到目前为止的前几行的计数,调整阈值,然后重置计数$2 > threshold
块的之后,否则计数将减少一个awk -f count.awk INput.txt > OUTput.txt