Bash - 将文件的每一行配对

Bash - 将文件的每一行配对

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

例子

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

a
b
c
d
e

那么我的结果应该是这样的:

a b
a c
a d
a e
b c
b d
b e
c d
c e
d e

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

答案1

使用这个命令:

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

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

(这确实不是要求对输入进行排序。)

答案2

如果您已经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
  • -0777slurp整个文件(应该没问题,因为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


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


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

答案3

$ 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

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

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

awk命令读取此结果,并且仅输出尚未见过的对的结果。

答案4

这是一个纯外壳的。

test $# -gt 1 || exit
a=$1
shift
for f in "$@"
do
  echo $a $f
done
exec /bin/sh $0 "$@"

例子:

~ (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) $ 

相关内容