我正在尝试使用shell脚本(以及“单行”)来查找大约50个文件之间的任何公共行。 修改:注意我正在寻找所有文件中出现的一行(行)
到目前为止,我已经尝试了grep grep -v -x -f file1.sp *
,它只是匹配所有其他文件中的文件内容。
我也尝试了grep -v -x -f file1.sp file2.sp | grep -v -x -f - file3.sp | grep -v -x -f - file4.sp | grep -v -x -f - file5.sp
等...但我相信使用要搜索的文件作为STD搜索而不是匹配的模式。
有人知道怎么用grep或其他工具吗?
我不介意运行需要一段时间,我必须在大约500个文件中添加几行代码,并希望在每个文件中找到一条公共行,以便插入'after'(它们原本只是一个文件中的c& p所以希望有一些共同的行!)
感谢您的时间,
答案 0 :(得分:3)
当我第一次阅读本文时,我以为你试图找到'任何共同的线'。我把它当作“找到重复的行”的意思。如果是这种情况,以下内容就足够了:
sort *.sp | uniq -d
重新阅读您的问题后,您似乎正在尝试查找“出现在所有文件中”的行。如果是这种情况,您需要知道目录中的文件数:
find . -type f -name "*.sp" | wc -l
如果这返回数字50,则可以使用awk
,如下所示:
WHINY_USERS=1 awk '{ array[$0]++ } END { for (i in array) if (array[i] == 50) print i }' *.sp
你可以整合这个过程并写一个单行代码:
WHINY_USERS=1 awk -v find=$(find . -type f -name "*.sp" | wc -l) '{ array[$0]++ } END { for (i in array) if (array[i] == find) print i }' *.sp
答案 1 :(得分:2)
结合这两个答案(ans1和ans2)我认为您可以在不对文件进行排序的情况下获得所需的结果:
#!/bin/bash
ans="matching_lines"
for file1 in *
do
for file2 in *
do
if [ "$file1" != "$ans" ] && [ "$file2" != "$ans" ] && [ "$file1" != "$file2" ] ; then
echo "Comparing: $file1 $file2 ..." >> $ans
perl -ne 'print if ($seen{$_} .= @ARGV) =~ /10$/' $file1 $file2 >> $ans
fi
done
done
只需保存它,赋予它执行权限(chmod +x compareFiles.sh
)并运行它。它将获取当前工作目录中存在的所有文件,并将在“matching_lines”文件中进行全对比比较结果。
有待改进的地方:
希望这有帮助。
最佳,
Alan Karpovsky
答案 2 :(得分:1)
见this answer。我原来虽然diff
听起来像你要求的,但这个答案似乎更合适。
答案 3 :(得分:1)
2 * n
个文件)从@ mjgpy3回答,您只需要进行for循环并使用comm
,如下所示:
#!/bin/bash
tmp1="/tmp/tmp1$RANDOM"
tmp2="/tmp/tmp2$RANDOM"
cp "$1" "$tmp1"
shift
for file in "$@"
do
comm -1 -2 "$tmp1" "$file" > "$tmp2"
mv "$tmp2" "$tmp1"
done
cat "$tmp1"
rm "$tmp1"
保存在comm.sh
中,将其设为可执行文件,然后调用
./comm.sh *.sp
假设您的所有文件名都以.sp
结尾。
看看其他答案,我想给每个文件打开一次而不使用任何临时文件,并支持重复的行。另外,让我们并行处理文件。
你去(在python3中):
#!/bin/env python
import argparse
import sys
import multiprocessing
import os
EOLS = {'native': os.linesep.encode('ascii'), 'unix': b'\n', 'windows': b'\r\n'}
def extract_set(filename):
with open(filename, 'rb') as f:
return set(line.rstrip(b'\r\n') for line in f)
def find_common_lines(filenames):
pool = multiprocessing.Pool()
line_sets = pool.map(extract_set, filenames)
return set.intersection(*line_sets)
if __name__ == '__main__':
# usage info and argument parsing
parser = argparse.ArgumentParser()
parser.add_argument("in_files", nargs='+',
help="find common lines in these files")
parser.add_argument('--out', type=argparse.FileType('wb'),
help="the output file (default stdout)")
parser.add_argument('--eol-style', choices=EOLS.keys(), default='native',
help="(default: native)")
args = parser.parse_args()
# actual stuff
common_lines = find_common_lines(args.in_files)
# write results to output
to_print = EOLS[args.eol_style].join(common_lines)
if args.out is None:
# find out stdout's encoding, utf-8 if absent
encoding = sys.stdout.encoding or 'utf-8'
sys.stdout.write(to_print.decode(encoding))
else:
args.out.write(to_print)
将其保存到find_common_lines.py
,然后致电
python ./find_common_lines.py *.sp
使用--help
选项的更多使用信息。