我有一个名称和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.txt
Mike 2000|Mike 20003|Mike 20002
。 - 线
for ((i=0; i<${#ary[@]}; i++)); do ..
创建地图 数字的模式。 - 表达式
"${num[$(cut -f 1-2 <<<"$line")]}"
检索该行 输出的第一个和第 2 个字段中的数字。
如果性能仍然不理想,请考虑ripgrep
比grep
或zgrep
快得多。