任何想法,为什么排序实用程序给了我不正确的结果?(Any idea why sort utility

2019-09-26 15:38发布

编辑:要明确,我们得到了我们从一个for循环STDOUT该是这样的

for (( i=1; i<="$FILE_AMOUNT"; i++ )); do
    MY_FILE=`find $DIR -type f | head -$i | tail -1`
    FILE_TYPE=`file -b "$MY_FILE"
    FILE_TYPE_COUNT=`echo $FILE_TYPE" | sort | uniq -c`
    echo "$FILE_TYPE_COUNT"
done

因此,我们的标准输出基本上是从印刷逐个文件实用程序输出,而不是将其actualling被设置字符串,我们可以复制 - 这很可能是后面的所有问题的核心




`

所以这是一个泡菜我绝对不能换我的头周围。

基本上我创建一个shell脚本,将打印出我们在我们的目录中的文件类型不同。 它几乎工程,但是,当我尝试对我的输出使用uniq的一些奇怪的原因,它不工作。 这是我的输出

POSIX shell script, ASCII text executable
ASCII text
Bourne-Again shell script, ASCII text executable
UTF-8 Unicode text, with overstriking
Bourne-Again shell script, ASCII text executable

似乎相当不言自明的,但是当我使用

FILE_TYPE_COUNT=`echo "$FILE_TYPE" | sort | uniq -c`

这是它打印出结果

  1 POSIX shell script, ASCII text executable
  1 ASCII text
  1 Bourne-Again shell script, ASCII text executable
  1 UTF-8 Unicode text, with overstriking
  1 Bourne-Again shell script, ASCII text executable

显然,这应该是

  1 POSIX shell script, ASCII text executable
  1 ASCII text
  2 Bourne-Again shell script, ASCII text executable
  1 UTF-8 Unicode text, with overstriking

任何想法,我做错了什么?

显然uniq的认为线是没有什么不同,但是这就是我认为什么是排序的过错,因为它不能排序我的标准输出。 因此,任何线索,如何正确地按字母顺序排序列表?

Answer 1:

你的做法似乎过于复杂,试试这个:

find $DIR -type f -exec file -b -- {} \; | sort | uniq -c

如果找你不熟悉-exec ,它执行给定的命令,在我们的案例file -b -- {}每个文件一次。 占位符{}被替换的路径当前正被处理的文件。

为什么你的做法不工作:

你这样做echo $FILE_TYPE" | sort | uniq -c中的for循环, $FILE_TYPE只包含在这一点上一个文件的文件类型,你需要移动。 sort | uniq -c圈外。

我调整你的代码,所以它的工作原理:

declare -a TYPES=()
for (( i=1; i<="$FILE_AMOUNT"; i++ )); do
    MY_FILE=`find a/ -type f | head -$i | tail -1`
    FILE_TYPE=`file -b "$MY_FILE"`
    TYPES+=("$FILE_TYPE") # add type of current file to TYPES array
done

# TYPES now contains the types of all files and we can now count them
printf "%s\n" "${TYPES[@]}" | sort | uniq -c


Answer 2:

你所看到的问题是因为你选了一组一个项目,为循环的每个迭代。

你需要循环的整体输出,而不是进行排序。

你(语法固定)脚本:

for (( i=1; i<="$FILE_AMOUNT"; i++ )); do
    MY_FILE=`find $DIR -type f | head -$i | tail -1`
    FILE_TYPE=`file -b "$MY_FILE"`
    FILE_TYPE_COUNT=`echo "$FILE_TYPE" | sort | uniq -c`
    echo "$FILE_TYPE_COUNT"
done

Mofified正常工作:

for (( i=1; i<="$FILE_AMOUNT"; i++ )); do
    MY_FILE=`find $DIR -type f | head -$i | tail -1`
    file -b "$MY_FILE"
done | sort | uniq -c

优化一次:

for FILE in $(find $DIR -type f); do
    file -b "$FILE"
done | sort | uniq -c

优化的两倍(见@P格柏的答案。):

find $DIR -type f -exec file -b -- {} \; | sort | uniq -c

您的原始脚本是惊人,效率低下。

效率和操作的注意事项:

  • ${FILE_AMOUNT}必须正确遍历整个数据集
  • 您正在运行find ,它返回整个数据集,然后丢弃你不感兴趣, 每次迭代的一切
  • 您正在运行sortuniq ,在每个迭代上,对大小为一的数据集
  • 当你不断地重新计算你的数据集,如果通过你的脚本执行改变半路上(例如:文件/目录中创建/删除),那么你的成绩将无效
  • 请记住,每次开始一个新的程序时,你付出性能上的损失 - 这是事实,你不断地计算你的数据集,然后丢弃“你不想要的一切”加剧


Answer 3:

在这里除了其他好的解决办法,一定要明白,你所使用的排序规则集。 检查你当前的排序规则,你可以这样做:

echo anything | sort --debug

看到你的结果与注解。 考虑:

echo -e "a 2\na1" | sort --debug
sort: using ‘en_US.UTF-8’ sorting rules
a1
__
a 2
___

请注意,规则集有可能是一个意想不到的结果排序。 如果你正在寻找一个简单的字节比较,则一定要设置LC_ALL=C ,如下所示:

LC_ALL=C sort

例如:

echo -e "a 2\na1" | LC_ALL=C sort --debug
sort: using simple byte comparison
a 2
___
a1
__

使用的LC_ALL是让你期望的结果很重要。 最后,运行locale指挥和阅读man页面以获取特定区域设置信息。



文章来源: Any idea why sort utility gives me incorrect results?
标签: bash shell