我想提取所有文件中存在的常见数字。我的文件夹中有 1000 个文件。我想比较所有文件编号并找出1000个文件中的共同编号。我使用了下面的代码:
for ((i=2;i<=10000;i++))
do
comm -12 --nocheck-order a.txt "$i".txt > final.txt
mv final.txt file.txt
done
但它只是重写并仅将最后一个文件与 a.txt 进行比较。但我希望所有文件中都存在通用编号。
假设有一个.txt 文件:
1
3
47
8
6
7
1.txt文件:
2
3
6
7
8
2.txt文件:
3
5
6
7
9
3.txt和4.txt....1000.txt。如果这对于这 3 个文件来说效果很好,那么它应该对于所有文件都效果很好。该文件中常见的是:
3
7
当它给我的时候
3
8
3
请让我知道我该如何继续?
答案1
假设每个数字在文件中只能出现一次:
$ awk '{c[$1]++} END{for (i in c) if (c[i] == (ARGC-1)) print i}' a.txt {1..2}.txt
3
6
7
答案2
comm
仅适用于已排序的文件,
比较已排序逐行读取文件 FILE1 和 FILE2。
来源 :https://linux.die.net/man/1/comm
因此该算法不适用于未排序的文件。这有效:
#!/bin/sh
sort -n a.txt > tmp.txt
END=4
for i in `seq 2 $END`
do
comm -12 --nocheck-order tmp.txt $i.txt |tee tmp.txt
done
cp tmp.txt "final.txt"
除了 之外,|tee
您还可以>
在某些系统上使用运算符(写入文件并覆盖它)
答案3
首先要知道,要comm
正确报告多个文件之间的公共行,您需要将输入文件按排序传递(如果它们之前尚未排序)。
其次,您需要将mv
命令更改为mv final.txt a.txt
;为了根据先前尝试的结果检查下一个文件;在这里,我从中进行了备份a.txt
并common.txt
在 for 循环中对其进行迭代。
所以你将得到如下的最终脚本:
cp a.txt common.txt
for ((i=1;i<=10000;i++));
do comm -12 <(sort common.txt) <(sort $i.txt) >temp.txt;
mv temp.txt common.txt;
done
最后cat common.txt
将是 10000 个文件中常见的那些行。
答案4
除了其他问题之外,您的脚本循环调用了comm
10000 次,导致速度非常慢。更快的替代方法是将它们全部排序并计算重复次数。所有文件中都存在计数等于文件数的行(如果每个文件内的值不重复):
set -- ./*.txt
sort -n "$@" | uniq -c | awk -vcount="$#" '$1==count{print $2}'
我使用位置参数来获取文件列表"$@"
和文件计数$#
。
-n
当您要求时,排序是数字数字。
你可以查看(并排序)没有文件具有重复的数字:
set -- ./*.txt
for f; do
sort -n "$f" > "$f.tempfile"
mv "$f.tempfile" "$f"
if [ "$(uniq -d "$f")" != "" ]; then echo $f; fi
done
这将列出所有具有重复编号的文件,并对每个单独的文件进行排序。