如何找到多个文件(不一定是两个文件)的交集?

如何找到多个文件(不一定是两个文件)的交集?

我想编写一个简单的脚本来查找交集多个文件(所有文件中的公共行),所以在阅读了一些内容之后(关联)我尝试编写一个 bash 脚本,不幸的是我失败了。我究竟做错了什么?

RES=$(comm -12 ${1}  ${2})

for FILE in ${@:3}
do
    RES=$(comm -12 $FILE  ${RES})
done

还有其他建议如何使用parallelor来实现这一点吗xargs

答案1

函数允许递归方法

f() {
     if (($# == 1))
     then
         cat $1;
         return;
     fi
     comm -12 $1 <(f "${@:2}")
}

f file1 file2 file3 file4 file5...

答案2

当您取消引用RES时:

comm $FILE  ${RES}

的内容RES替换${RES}.但comm需要一个文件名作为参数,因此例如 if $REScontainshello comm尝试打开名为hello.

相反,您可以使用临时文件来存储过程中的公共行:

tmp=$(mktemp --tmpdir)
tmp2=$(mktemp --tmpdir)
comm -12 ${1}  ${2} >$tmp

for FILE in ${@:3}
do
    comm -12 $FILE  $tmp >$tmp2
    rm $tmp 
    mv $tmp2 $tmp   
done

cat $tmp 
rm $tmp

答案3

没有parallelxargs没有comm必要。尝试一个功能

$ intersection() {  sort $@ | uniq -c | sed -n "s/^ *$# //p"; }
$ intersection file[1-3]
line2
line4

答案4

问题是comm需要两个文件,并且$RES是一个变量。

但我们可以欺骗并通过使用进程替换使其看起来像一个文件:

#!/bin/bash

RES=$(comm -12 ${1}  ${2})

for FILE in ${@:3}
do
    RES="$(comm -12 $FILE  <(printf %s "${RES}"))"
done

printf %s "$RES"

您可以看到这与原来的几乎相同,但是我们使用结构<(...)来运行命令并将其用作文件名。

所以如果我们有这三个文件:

a:line1
a:line2
a:line3
a:line4
b:line2
b:line4
b:line6
c:line2
c:line4
c:line8

我们可以对它们进行比较:

% ./allcomp a b c
line2
line4

相关内容