Awk 按强制顺序按特定元素筛选文件
我试图通过索引列过滤文件,并确保留下一些数字。在原始文件file1.txt中,索引列通常具有0到10之间的任意数字 示例文件中的破折号将每个块彼此分开:Awk 按强制顺序按特定元素筛选文件,awk,filter,range,Awk,Filter,Range,我试图通过索引列过滤文件,并确保留下一些数字。在原始文件file1.txt中,索引列通常具有0到10之间的任意数字 示例文件中的破折号将每个块彼此分开: file1.txt index age_1 age_2 0 44 34 1 10 12 1 34 44 2 1 -3 3 4 -10.3 3 3.390 4 4 43 3 -- 1 -90
file1.txt
index age_1 age_2
0 44 34
1 10 12
1 34 44
2 1 -3
3 4 -10.3
3 3.390 4
4 43 3
--
1 -90.3 2
2 32 3
3 43 -20
4 2 2
--
0 34 34
2 21 12
4 -0.9 12
--
4 -2.19 34
4 4 4
5 5 -1
6 4 12
--
3 -12 3
我试图分别过滤破折号之间的每个块,并将索引列中的范围从1到4的块与每个元素1、2、3、4至少保持一次。
因此,预期输出如下所示:
index age_1 age_2
1 10 12
1 34 44
2 1 -3
3 4 -10.3
3 3.390 4
4 43 3
--
1 -90.3 2
2 32 3
3 43 -20
4 2 2
我当前的试用版只能检查索引列中的范围,但我无法指定强制筛选:
cat file1.txt | awk -v OFS="\t" '$1=$1' | tail -n +2 | awk '$1>=1 && $1<=4'
1 10 12
1 34 44
2 1 -3
3 4 -10.3
3 3.390 4
4 43 3
1 -90.3 2
2 32 3
3 43 -20
4 2 2
2 21 12
4 -0.9 12
4 -2.19 34
4 4 4
3 -12 3
我丢失了块,所有的输出在没有特定过滤的情况下都是混合的。它可以打印1到4之间的任何数字
如何通过将每个区块分开来对特定列中的数字进行严格筛选?要确定区块的第一列是否包含所选范围内的所有数字,您可以在处理区块时索引数组中的第一列元素,并将其长度与末尾的范围大小进行比较,如中所述下面是脚本
$ cat tst.awk
NR == 1 {
print
next
}
$1 == "--" {
if (length(arr) == 4) {
printf "%s%s", sep, buf
}
sep = ($0 ORS)
buf = ""
delete arr
}
$1 >= 1 && $1 <= 4 {
buf = (buf $0 ORS)
arr[$1]
}
END {
if (length(arr) == 4) {
printf "%s%s", sep, buf
}
}
要确定块的第一列是否包含选定范围内的所有数字,可以在处理块的同时对数组中的第一列元素进行索引,并将其长度与末尾的范围大小进行比较,如下面的脚本所示
$ cat tst.awk
NR == 1 {
print
next
}
$1 == "--" {
if (length(arr) == 4) {
printf "%s%s", sep, buf
}
sep = ($0 ORS)
buf = ""
delete arr
}
$1 >= 1 && $1 <= 4 {
buf = (buf $0 ORS)
arr[$1]
}
END {
if (length(arr) == 4) {
printf "%s%s", sep, buf
}
}
这只是编写解决方案的一种稍微不同的方法。我们提出了同样的方法,但他先发布了。我对他的进行了升级,并打算删除我的,但最终决定将其留在这里,作为实现相同方法的替代方法。主要区别在于我使用了一个函数来包含打印代码,以防有人感兴趣,但他是第一个,所以他应该获得投票
$ cat tst.awk
NR==1 { print; next }
($1 >= 1) && ($1 <= 4) {
rec = rec $0 ORS
hits[$1]
}
$1 == "--" {
rec = rec $0 ORS
prt()
}
END { prt() }
function prt() {
if ( length(hits) == 4 ) {
printf "%s", rec
}
rec = ""
delete hits
}
$ awk -f tst.awk file
index age_1 age_2
1 10 12
1 34 44
2 1 -3
3 4 -10.3
3 3.390 4
4 43 3
--
1 -90.3 2
2 32 3
3 43 -20
4 2 2
--
这只是编写解决方案的一种稍微不同的方法。我们提出了同样的方法,但他先发布了。我对他的进行了升级,并打算删除我的,但最终决定将其留在这里,作为实现相同方法的替代方法。主要区别在于我使用了一个函数来包含打印代码,以防有人感兴趣,但他是第一个,所以他应该获得投票
$ cat tst.awk
NR==1 { print; next }
($1 >= 1) && ($1 <= 4) {
rec = rec $0 ORS
hits[$1]
}
$1 == "--" {
rec = rec $0 ORS
prt()
}
END { prt() }
function prt() {
if ( length(hits) == 4 ) {
printf "%s", rec
}
rec = ""
delete hits
}
$ awk -f tst.awk file
index age_1 age_2
1 10 12
1 34 44
2 1 -3
3 4 -10.3
3 3.390 4
4 43 3
--
1 -90.3 2
2 32 3
3 43 -20
4 2 2
--
我想说的是,如果你能为每一张唱片拆分1234,arr并删除arr[$1],不是更好吗?那你就这么做吧!lengtharr并打印块,但随后删除了。我经过了几次迭代,其中一次我认为OP想要列表中的1美元而不是范围中的1美元,当时我正在使用拆分。我想说,如果你拆分1 2 3 4,arr并删除每条记录的arr[$1],不是更好吗?那你就这么做吧!lengtharr并打印块,但随后删除了。我经过了几次迭代,其中一次我认为OP想要列表中的1美元而不是范围中的1美元,那是我使用拆分的时候。谢谢你的回答。这个解决方案确实有一个错误:致命:尝试使用标量'arr'作为数组,那么,arr在这里指的是什么?谢谢你的回答。这个解决方案确实有一个错误:致命:尝试使用标量'arr'作为数组。那么,arr在这里指的是什么?