我正在尝试找到一种解决方案,可以根据第二个文件键使用第一列对第一个文件进行排序
第一个文件示例 (file1.csv)
COLUMN1 COlUMN2
apple fruit
dog animal
cat animal
cow animal
第二个文件示例 (sort_keys.txt)
cat
dog
apple
cow
预期输出(sorted.txt)
COLUMN1 COlUMN2
cat animal
dog animal
apple fruit
cow animal
到目前为止,我已经找到了一个排序命令,并且 awk 命令可能会有所帮助,但我没有任何工作代码。
$> awk 'NR==FNR{o[FNR]=$1; next} {t[$1]=$0} END{for(x=1; x<=FNR; x++){y=o[x]; print t[y]}}' sort_key.txt file1.csv
但是,该命令未按预期工作,需要就此请求任何专家建议。 PS 我确实有 Linux 命令知识,但这是非常具体的,我不知道如何实现这一点。
非常感谢任何帮助或提示。
答案1
$ awk 'NR==1; NR==FNR{a[$1]=$2; next} {print $1, a[$1]}' file1 sort_keys.txt
COLUMN1 COlUMN2
cat animal
dog animal
apple fruit
cow animal
答案2
如果您有 GNU awk (又名gawk
),您可以定义并使用您自己的自定义排序函数。
例如,假设PROCINFO
数组遍历功能的 GNU awk > 4.0:
$ gawk '
function mysort(ia,va,ib,vb){return o[ia] - o[ib]}
NR==FNR{o[$1]=FNR; next} # map keys to numerical order
FNR==1{print; next} # print + skip the header line
{a[$1]=$0}
END{
PROCINFO["sorted_in"] = "mysort"
for(i in a) print a[i]
}
' sort_key.txt file1.csv
COLUMN1 COlUMN2
cat animal
dog animal
apple fruit
cow animal
(使用较旧的 GNU awks,您应该能够使用 来实现相同的目的asorti
。)
答案3
如果您的数据不是很大,这是一个具有二次复杂度的简单解决方案:
cat sort_keys.txt | while read key ; do egrep "^$key " file1.csv ; done
要添加/删除标头,请根据需要添加head
和命令。tail
答案4
你可以用join
它。从man join
:
对于具有相同连接字段的每对输入行,将一行写入标准输出。默认连接字段是第一个,由空格分隔。
请注意,第一行不得排序。
总长DR:
head -n 1 file1.csv; join -1 2 <(cat -n sort_keys.txt | sort -k 2) <(tail -n +2 file1.csv | sort) | sort -n -k 2 | awk '{ print $1, $3 }'
会做这项工作。
说明
我们基本上会:
- 提取 file1.csv 的第一行
- 在第一个字段上使用 sort_keys 连接 file1.csv 的剩余部分
- 按照sort_keys的顺序对结果进行排序
另外,join
需要对文件进行排序。
这将引导我们:
- 作为第一个输入,对 sort_keys 文件进行编号(在前置字段中)(以便能够在最后使用此原始顺序),然后对第二个字段进行排序
cat -n sort_keys.txt | sort -k 2
3 apple
1 cat
4 cow
2 dog
- 作为第二个输入,我们获取 csv 文件,跳过第一行,并在第一个字段上对其进行排序。
tail -n +2 file1.csv | sort
apple fruit
cat animal
cow animal
dog animal
- 然后我们可以使用第一个进程的第二个字段 (
-1 2
) 将其连接在一起:
join -1 2 <(cat -n sort_keys.txt | sort -k 2) <(tail -n +2 file1.csv | sort)
apple 3 fruit
cat 1 animal
cow 4 animal
dog 2 animal
- 连接结果现在可以在第二个字段上进行数字排序(如果 sort_keys 超过 9 个条目),并且我们只保留第一个和第三个字段
``... |排序 -n -k 2 | awk '{ 打印 $1, $3 }'
cat animal
dog animal
apple fruit
cow animal
- 最后,在 file1.csv 的第一行前面加上它
head -n 1 file1.csv; join -1 2 <(cat -n sort_keys.txt | sort -k 2) <(tail -n +2 file1.csv | sort) | sort -n -k 2 | awk '{ print $1, $3 }'
COLUMN1 COlUMN2
cat animal
dog animal
apple fruit
cow animal
更进一步
根据您的实际数据,您将必须调整字段编号和字段分隔符。
您可能还想保留其键不在 sort_keys 中的数据行,或者保留 sort_keys 中没有相应数据行的行(请参阅-a
join 选项)。
尽情使用join
!