bash 中按列合并行数不等的多个文件的更快方法
Faster way to merge multiple files with unequal number of rows by column in bash
我有多个文件,我想使用 shell 脚本按列合并,假设文件 a.txt 和文件 b.txt。文件 a.txt 包含排序的唯一值,第一列将用作参考值。
示例:
# cat a.txt
001|johan
002|mike
003|adam
# cat b.txt
001|chu
001|stewart
002|lewis
002|jordan
003|lambert
003|johnson
003|smith
003|long
这两个文件将合并生成如下所示的输出。
# cat c.txt
001|johan chu
001|johan stewart
002|mike lewis
002|mike jordan
003|adam lambert
003|adam johnson
003|adam smith
003|adam long
我尝试使用 while do
进行简单迭代。
while read line
do
ids=`echo $line | awk -F"|" '{print }'`
fn=`grep $ids a.txt`
echo $fn"|"$line | awk -F"|" '{print "|"" "}'
done < b.txt > c.txt
但是如果我有百万行,这会花费很多时间。
在 MySQL
中,我们可以使用 JOIN
子句轻松实现它。但我们需要先 load/insert 他们。
更快的方法可能是使用 paste
命令,但据我所知,两个文件的总行数必须相等。那我可以先调整a.txt。但是当脚本 运行.
时仍然消耗很多时间
也许有人有更好的方法。
您可以将所有内容放在一个 awk
脚本中:
awk -F'|' '{if (NR==FNR) a[]=; else print "|" a[] " " }' a.txt b.txt
001|johan chu
001|johan stewart
002|mike lewis
002|mike jordan
003|adam lambert
003|adam johnson
003|adam smith
003|adam long
假设:
- 两个文件都按第 1 列排序
- 忽略在相反文件中没有匹配项的行
使用 join
和 sed
的一个想法(删除第二个 |
):
join -t'|' -o 1.1,1.2,2.2 a.txt b.txt | sed -E 's/\|([^|]*$)/ /'
一个awk
想法:
awk '
BEGIN { FS=OFS="|" }
FNR==NR { a[]=; next }
in a { print ,a[] " " }
' a.txt b.txt
这两个生成:
001|johan chu
001|johan stewart
002|mike lewis
002|mike jordan
003|adam lambert
003|adam johnson
003|adam smith
003|adam long
我有多个文件,我想使用 shell 脚本按列合并,假设文件 a.txt 和文件 b.txt。文件 a.txt 包含排序的唯一值,第一列将用作参考值。
示例:
# cat a.txt
001|johan
002|mike
003|adam
# cat b.txt
001|chu
001|stewart
002|lewis
002|jordan
003|lambert
003|johnson
003|smith
003|long
这两个文件将合并生成如下所示的输出。
# cat c.txt
001|johan chu
001|johan stewart
002|mike lewis
002|mike jordan
003|adam lambert
003|adam johnson
003|adam smith
003|adam long
我尝试使用 while do
进行简单迭代。
while read line
do
ids=`echo $line | awk -F"|" '{print }'`
fn=`grep $ids a.txt`
echo $fn"|"$line | awk -F"|" '{print "|"" "}'
done < b.txt > c.txt
但是如果我有百万行,这会花费很多时间。
在 MySQL
中,我们可以使用 JOIN
子句轻松实现它。但我们需要先 load/insert 他们。
更快的方法可能是使用 paste
命令,但据我所知,两个文件的总行数必须相等。那我可以先调整a.txt。但是当脚本 运行.
时仍然消耗很多时间
也许有人有更好的方法。
您可以将所有内容放在一个 awk
脚本中:
awk -F'|' '{if (NR==FNR) a[]=; else print "|" a[] " " }' a.txt b.txt
001|johan chu
001|johan stewart
002|mike lewis
002|mike jordan
003|adam lambert
003|adam johnson
003|adam smith
003|adam long
假设:
- 两个文件都按第 1 列排序
- 忽略在相反文件中没有匹配项的行
使用 join
和 sed
的一个想法(删除第二个 |
):
join -t'|' -o 1.1,1.2,2.2 a.txt b.txt | sed -E 's/\|([^|]*$)/ /'
一个awk
想法:
awk '
BEGIN { FS=OFS="|" }
FNR==NR { a[]=; next }
in a { print ,a[] " " }
' a.txt b.txt
这两个生成:
001|johan chu
001|johan stewart
002|mike lewis
002|mike jordan
003|adam lambert
003|adam johnson
003|adam smith
003|adam long