Bash - 配对文件的每一行

Enn*_*nno 11 shell-script text-processing

这个问题与这个这个问题密切相关。我有一个包含多行的文件,其中每一行都是文件的路径。现在我想将每条线与每条不同的线(不是它本身)配对。此外,就我而言,一对A B等于一B A对,因此只应生成这些组合中的一个。

例子

files.dat 在速记符号中读起来像这样,每个字母都是一个文件路径(绝对或相对)

a
b
c
d
e
Run Code Online (Sandbox Code Playgroud)

然后我的结果应该是这样的:

a b
a c
a d
a e
b c
b d
b e
c d
c e
d e
Run Code Online (Sandbox Code Playgroud)

最好我想在 bash 中解决这个问题。与其他问题不同,我的文件列表相当小(大约 200 行),因此使用循环和 RAM 容量没有问题。

Kus*_*nda 8

$ join -j 2 -o 1.1,2.1 file file | awk '!seen[$1,$2]++ && !seen[$2,$1]++'
a b
a c
a d
a e
b c
b d
b e
c d
c e
d e
Run Code Online (Sandbox Code Playgroud)

这假设输入文件中没有任何行包含任何空格。它还假定文件已排序

join命令创建文件中各行的完整叉积。它通过在不存在的字段上将文件与自身连接来实现此目的。非标准-j 2可能被替换为-1 2 -2 2(但-j2除非你使用 GNU 否则不能被替换join)。

awk命令读取此结果并仅输出尚未看到的结果对。


G-M*_*ca' 8

使用这个命令:

awk '{ name[$1]++ }
    END { PROCINFO["sorted_in"] = "@ind_str_asc"
        for (v1 in name) for (v2 in name) if (v1 < v2) print v1, v2 }
        ' files.dat
Run Code Online (Sandbox Code Playgroud)

PROCINFO可能是一个gawk扩展。如果您awk不支持它,只需省略该PROCINFO["sorted_in"] = "@ind_str_asc"行并将输出通过管道输入sort(如果您希望输出排序)。

(这并没有要求要排序的输入。)


iru*_*var 8

一个python解决方案。输入文件itertools.combinations来自标准库,它生成 2 长度的元组,这些元组被格式化并打印到标准输出。

python3 -c 'from itertools import combinations
with open("file") as f:
    lines = (line.rstrip() for line in f)
    lines = ("{} {}".format(x, y) for x, y in combinations(lines, 2))
    print(*lines, sep="\n")
'
Run Code Online (Sandbox Code Playgroud)


Sun*_*eep 7

如果您已ruby安装:

$ ruby -0777 -F'\n' -lane '$F.combination(2) { |c| puts c.join(" ")}' ip.txt
a b
a c
a d
a e
b c
b d
b e
c d
c e
d e
Run Code Online (Sandbox Code Playgroud)
  • -0777 slurp 整个文件(应该没问题,因为它在 OP 中提到文件大小很小)
  • -F'\n'基于换行符分割,所以每一行都是$F数组中的一个元素
  • $F.combination(2)一次生成组合2元素
  • { |c| puts c.join(" ")} 根据需要打印
  • 如果输入文件可以包含重复项,请使用 $F.uniq.combination(2)


一次 3 个元素:

$ ruby -0777 -F'\n' -lane '$F.combination(3) { |c| puts c.join(" ")}' ip.txt
a b c
a b d
a b e
a c d
a c e
a d e
b c d
b c e
b d e
c d e
Run Code Online (Sandbox Code Playgroud)


perl(非通用)

$ perl -0777 -F'\n' -lane 'for $i (0..$#F) {
                             for $j ($i+1..$#F) { 
                               print "$F[$i] $F[$j]\n" } }' ip.txt
a b
a c
a d
a e
b c
b d
b e
c d
c e
d e
Run Code Online (Sandbox Code Playgroud)


awk

$ awk '{ a[NR]=$0 }
       END{ for(i=1;i<=NR;i++)
              for(j=i+1;j<=NR;j++)
                print a[i], a[j] }' ip.txt 
a b
a c
a d
a e
b c
b d
b e
c d
c e
d e
Run Code Online (Sandbox Code Playgroud)


EdC*_*EdC 5

这是一个纯外壳的。

test $# -gt 1 || exit
a=$1
shift
for f in "$@"
do
  echo $a $f
done
exec /bin/sh $0 "$@"
Run Code Online (Sandbox Code Playgroud)

例子:

~ (137) $ sh test.sh $(cat file.dat)
a b
a c
a d
a e
b c
b d
b e
c d
c e
d e
~ (138) $ 
Run Code Online (Sandbox Code Playgroud)