如何根据第二个文件键对第一个文件 (csv) 进行排序

如何根据第二个文件键对第一个文件 (csv) 进行排序

我正在尝试找到一种解决方案,可以根据第二个文件键使用第一列对第一个文件进行排序

第一个文件示例 (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 中没有相应数据行的行(请参阅-ajoin 选项)。

尽情使用join

相关内容