Grep Shell:在多个文件中查找匹配行

Grep Shell:在多个文件中查找匹配行,grep,Grep,我正在尝试使用shell脚本(也就是“一行”)来查找大约50个文件之间的任何公共行。 编辑:注意,我正在查找所有文件中出现的一行(多行) 到目前为止,我已经尝试了grepgrep-v-x-f file1.sp*,它只在所有其他文件中匹配该文件的内容 我还尝试了grep-v-x-f文件1.sp文件2.sp | grep-v-x-f-file3.sp | grep-v-x-f-file4.sp | grep-v-x-f-file5.sp等等。。。但我相信,使用要作为STD搜索的文件进行搜索并不是要匹

我正在尝试使用shell脚本(也就是“一行”)来查找大约50个文件之间的任何公共行。 编辑:注意,我正在查找所有文件中出现的一行(多行)

到目前为止,我已经尝试了grep
grep-v-x-f file1.sp*
,它只在所有其他文件中匹配该文件的内容

我还尝试了
grep-v-x-f文件1.sp文件2.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,所以希望有一些共同的代码行!)


谢谢您的时间,请参见。我最初认为a
diff
听起来像是你想要的,但这个答案似乎更合适。

当我第一次读到这篇文章时,我以为你在寻找“任何共同点”。我把它理解为“查找重复行”的意思。如果是这种情况,以下内容就足够了:

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

您可以合并此过程并编写一行程序,如下所示:

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
旧的bash应答(O(n);打开
2*n
文件) 从@mjgpy3 answer开始,您只需创建一个for循环并使用
comm
,如下所示:

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
#/bin/bash
tmp1=“/tmp/tmp1$RANDOM”
tmp2=“/tmp/tmp2$RANDOM”
cp“$1”$tmp1”
转移
对于“$@”中的文件
做
comm-1-2“$tmp1”“$file”>“$tmp2”
mv“$tmp2”“$tmp1”
完成
类别“$tmp1”
rm“$tmp1”
保存在
comm.sh
中,使其可执行,然后调用

./comm.sh *.sp 
python ./find_common_lines.py *.sp
假设所有文件名都以
.sp
结尾

更新的答案是python,每个文件只打开一次 看看其他答案,我想给出一个在不使用任何临时文件的情况下打开每个文件一次,并且支持重复行的答案。另外,让我们并行处理这些文件

给你(在蟒蛇3中):

#/bin/env python
导入argparse
导入系统
导入多处理
导入操作系统
EOLS={'native':os.linesep.encode('ascii'),'unix':b'\n','windows':b'\r\n'}
def extract_集合(文件名):
将open(filename,'rb')作为f:
返回集(f中的行的行.rstrip(b'\r\n'))
def find_common_行(文件名):
池=多处理。池()
line_set=pool.map(提取_set,文件名)
返回集合。交点(*线集合)
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
#用法信息和参数解析
parser=argparse.ArgumentParser()
add_参数(“在_文件中”,nargs='+',
help=“查找这些文件中的公用行”)
parser.add_参数('--out',type=argparse.FileType('wb'),
help=“输出文件(默认标准输出)”)
parser.add_参数('--eol style',choices=EOLS.keys(),default='native',
help=“(默认值:本机)”)
args=parser.parse_args()
#实物
公共线=查找公共线(文件中的参数)
#将结果写入输出
to_print=EOLS[args.eol_style]。连接(公共线)
如果args.out为无:
#找出标准输出的编码,如果不存在utf-8
编码=sys.stdout.encoding或“utf-8”
系统标准输出写入(打印解码(编码))
其他:
参数输出写入(打印)
将其保存到一个
find_common_lines.py
,然后调用

./comm.sh *.sp 
python ./find_common_lines.py *.sp

使用
--help
选项了解更多使用信息。

结合这两个答案(和),我认为您可以获得所需的结果,而无需对文件进行排序:

#!/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
)并运行它。它将获取当前工作目录中的所有文件,并将所有与所有进行比较,结果保留在“匹配_行”文件中

需要改进的地方:

  • 跳过目录
  • 避免对所有文件进行两次比较(file1与file2和file2与file1)
  • 可能在匹配字符串旁边添加行号
希望这有帮助

最好的


艾伦·卡波夫斯基(Alan Karpovsky)

这个答案似乎不支持很多文件?这只是关于在两个文件中查找行的信息,我正在尝试在许多文件中查找行小心:您的算法运行在
O(n**2)
复杂情况下,对于重复行将失败。想象一个文件有50个相同的lines@bernardpaulus:OP表示“公用线”,因此DUP不存在。另请参见