【问题标题】:Sorting issue in Bash ScriptBash 脚本中的排序问题
【发布时间】:2024-05-18 18:15:02
【问题描述】:

我有一个完整的文件,其中包含从下面的 find 命令输出的文件名:

find "$ARCHIVE" -type f -name *_[0-9][0-9] | sed 's/_[0-9][0-9]$//' > temp

我现在正在尝试对这些文件名进行排序并计算它们以找出出现最多的文件名。我遇到的问题是每当我执行时:

sort -g temp

它将所有排序的文件名打印到命令行,我不确定为什么。任何有关此问题的帮助将不胜感激!

【问题讨论】:

  • Sort 不对文件进行就地排序,它接受输入并对其进行排序并将其打印到标准输出,如果您愿意,您可以将其重定向到另一个文件(虽然不是同一个文件,因为您'如果你这样做,将开始覆盖你试图读取的文件)
  • 你能发布一个temp的简短例子吗?您想计算文件在文档中出现的次数,对吗?
  • @PedroLobito 我已经发布了temp 的简短摘录,是的,你是对的。

标签: bash sorting sed find filenames


【解决方案1】:

你可能需要这个:

sort temp| uniq -c | sort -nr

首先我们sort temp,然后我们在行前面加上出现次数(uniq -c),接下来我们根据字符串数值比较(sort -n),最后一个命令反转比较结果(sort -r )。


示例文件:

/home/user/testfiles/405/prob405823
/home/user/testfiles/405/prob405823
/home/user/testfiles/527/prob527149
/home/user/testfiles/518/prob518433

输出:

  2 /home/user/testfiles/405/prob405823
  1 /home/user/testfiles/527/prob527149
  etc..

资源:

Linux / Unix Command: sort
uniq(1) - Linux man page
ptierno - comments to improve answer

【讨论】:

  • 你可以直接退出cat temp,只需要sort temp | uniq -c |sort -nr
  • ...或sort <temp | ...,如果出于某种原因不想让sort 负责打开文件。在任何一种情况下,sorttemp 上拥有直接文件句柄肯定比从管道读取更有效。
  • (此外,当给定一个直接的、可搜索的文件句柄时,sort 甚至可以在文件开始处理内容之前查看文件的大小,并就是否需要写入临时文件或可以将所有内容保存在 RAM 中;当只给定一个管道时,该信息不可用)。
【解决方案2】:

您可以在一个 awk 命令中找到之后执行所有操作(此命令使用 GNU awk 4.*):

find "$ARCHIVE" -type f -name *_[0-9][0-9] |
awk '
{ cnt[gensub(/_[0-9][0-9]$/,"","")]++ }
END {
    PROCINFO["sorted_in"] = "@val_num_desc"
    for (file in cnt) {
        print cnt, file
    }
}
'

【讨论】:

  • 这里是否可以直接使用 NUL 分隔名称,从而至少在 find->awk 端用换行符消除名称的歧义? (当然,如果它们随后以模棱两可的形式从 awk 发出,也许这并不能买到任何有用的东西)。
  • 是的,您可以将 -print0 添加到 find 中,然后在 awk 命令中使用 -v RS='\0'。如果我们还设置了ORS='\0',那么如果有用的话,awk 也会以 NUL 分隔输出它们。
最近更新 更多