使用 bash 查询大制表符分隔文件



我有一个名称和ID列表(50个条目(

cat input.txt

name    ID
Mike    2000
Mike    20003
Mike    20002

并且有一个巨大的压缩文件(13GB(

zcat clients.gz

name    ID  comment
Mike    2000    foo
Mike    20002   bar
Josh    2000    cake
Josh    20002   _

我的预期输出是

NR  name    ID  comment
1    Mike   2000    foo
3    Mike   20002   bar

客户端的每个$1"t"$2.gz都是一个唯一的标识符。input.txt中可能缺少一些条目,clients.gz中可能缺少。因此,我想将 NR 列添加到我的输出中以找出缺少哪些列。我想使用 zgrep。awk 需要很长时间(因为我不得不zcat解压缩我假设的压缩文件?

我知道zgrep 'Miket2000'不起作用。我想我可以用awk FNR解决NR问题。

到目前为止,我有:

awk -v q="'" 
'
NR > 1 {
print "zcat clients.gz | zgrep -w $" q$0q
}' input.txt |
bash > subset.txt
$ cat tst.awk
BEGIN { FS=OFS="t" }
{ key = $1 FS $2 }
NR == FNR { map[key] = (NR>1 ? NR-1 : "NR"); next }
key in map { print map[key], $0 }
$ zcat clients.gz | awk -f tst.awk input.txt -
NR      name    ID      comment
1       Mike    2000    foo
3       Mike    20002   bar

使用 GNU awk 和 bash:

awk 'BEGIN{FS=OFS="t"} 
# process input.txt
NR==FNR{
a[$1,$2]=$1 FS $2
line[$1,$2]=NR-1
next
}
# process <(zcat clients.gz)
{
$4=a[$1,$2]
if(FNR==1)
line[$1,$2]="NR"
if($4!="")
print line[$1,$2],$1,$2,$3
}' input.txt <(zcat clients.gz)

输出:

NR 名称 ID 注释 1 迈克 2000 foo 3 迈克 20002 酒吧

作为一行:

awk 'BEGIN{FS=OFS="t"} NR==FNR{a[$1,$2]=$1 FS $2; line[$1,$2]=NR-1; next} {$4=a[$1,$2]; if(FNR==1) line[$1,$2]="NR"; if($4!="")print line[$1,$2],$1,$2,$3}' input.txt <(zcat clients.gz)

请参阅: 基于两个键列 awk 和 8 个强大的 Awk 内置变量连接两个文件 – FS、OFS、RS、ORS、NR、NF、FILENAME、FNR

[编辑]
我误解了前面的行号是从哪里来的。纠正。

您会尝试以下方法吗:

declare -A num          # asscoiates each pattern to the line number
mapfile -t ary < <(tail -n +2 input.txt)
pat=$(IFS='|'; echo "${ary[*]}")
for ((i=0; i<${#ary[@]}; i++)); do num[${ary[i]}]=$((i+1)); done
printf "%st%st%st%sn" "NR" "name" "ID" "comment"
zgrep -E -w "$pat" clients.gz | while IFS= read -r line; do
printf "%dt%sn" "${num[$(cut -f 1-2 <<<"$line")]}" "$line"
done

输出:

NR  name    ID  comment
1   Mike    2000    foo
3   Mike    20002   bar
  • 第二行和第三行生成搜索模式,作为input.txtMike 2000|Mike 20003|Mike 20002
  • 线for ((i=0; i<${#ary[@]}; i++)); do ..创建地图 数字的模式。
  • 表达式"${num[$(cut -f 1-2 <<<"$line")]}"检索该行 输出的第一个和第 2 个字段中的数字。

如果性能仍然不理想,请考虑ripgrepgrepzgrep快得多。

相关内容

  • 没有找到相关文章

最新更新