我有一个制表符分隔的文本文件,格式如下
Name city info
Stef NY=123 ID=1;CITY=NY
John SE=981;819 ID=110;CITY=SE
Stef SE=01 ID=20;CITY=SE
Kelly SE=111;787 ID=100;CITY=NY
Lena NY=815;981;1 ID=2111;CITY=NY
我想将行提取到一个新的文本文件中,其中第三列中的 ID 大于 100,因此预期输出变为:
Name city info
John SE=981;819 ID=110;CITY=SE
Lena NY=815;981,1 ID=2111;CITY=NY
到目前为止我拥有的 awk 命令是:
awk '$3 !~ /^ID=[0-9];/' file.txt > output.txt
但是,这只会删除 ID 等于或小于 9 的那些行。我不知道如何排除 ID 小于 100 的所有行。我怎样才能实现这一点。见解将不胜感激。
答案1
使用磨坊主
$ mlr --tsv filter 'i = splitkv($info, "=", ";"); i["ID"] > 100' file.txt
Name city info
John SE ID=110;CITY=SE
Lena NY ID=2111;CITY=NY
使用 GNU awk:
$ gawk -F '\t' 'NR==1 || match($3,/ID=([0-9]+)/,arr) && arr[1]+0 > 100' file.txt
Name city info
John SE ID=110;CITY=SE
Lena NY ID=2111;CITY=NY
答案2
假设您的真实输入类似于您提供的示例:
$ awk -F'[=;]' 'NR==1 || $(NF-2)>100' file
Name city info
John SE=981;819 ID=110;CITY=SE
Lena NY=815;981;1 ID=2111;CITY=NY
以下是如何将 FS 设置为[=;]
告诉 awk 将每个记录拆分为字段:
$ awk -F'[=;]' '{print "---------" ORS $0; for (i=1;i<=NF;i++) print NF, i, "<"$i ">"}' file
---------
Name city info
1 1 <Name city info>
---------
Stef NY=123 ID=1;CITY=NY
5 1 <Stef NY>
5 2 <123 ID>
5 3 <1>
5 4 <CITY>
5 5 <NY>
---------
John SE=981;819 ID=110;CITY=SE
6 1 <John SE>
6 2 <981>
6 3 <819 ID>
6 4 <110>
6 5 <CITY>
6 6 <SE>
---------
Stef SE=01 ID=20;CITY=SE
5 1 <Stef SE>
5 2 <01 ID>
5 3 <20>
5 4 <CITY>
5 5 <SE>
---------
Kelly SE=111;787 ID=100;CITY=NY
6 1 <Kelly SE>
6 2 <111>
6 3 <787 ID>
6 4 <100>
6 5 <CITY>
6 6 <NY>
---------
Lena NY=815;981;1 ID=2111;CITY=NY
7 1 <Lena NY>
7 2 <815>
7 3 <981>
7 4 <1 ID>
7 5 <2111>
7 6 <CITY>
7 7 <NY>
答案3
如果标题下方的整个文件的格式相同:
awk -F '=|;' 'NR==1; $2>100' location
它将分隔符设置为 或=
,;
打印标题,然后打印第一行之后第二个字段大于 100 的任何行。
输出:
Name city info
John SE ID=110;CITY=SE
Lena NY ID=2111;CITY=NY
答案4
一个非常幼稚的解决方案可能是:
awk -F'\t' '{
o=$3
sub(/ID=/,"",o)
if(o + 0 > 100) print
}' test
更先进的方法可能是:
awk -F'\t' 'NR == 1 || (match($3, /[0-9]+/) && substr($3, RSTART, RLENGTH) + 0 > 100)' test
尝试match
在第三个字段中输入至少 3 位数字。
match
将为我们RLENGTH
在正则表达式开始匹配的索引处设置变量,如果根本没有找到匹配,则在 0 处设置变量。
然后我们可以检查整个匹配项(从RSTART
到RLENGTH
)是否大于 100。如果是,则打印整行。