Bash - ファイルの各行をペアリングします。

Bash - ファイルの各行をペアリングします。

この質問は以下に関連しています。これそしてこれ質問。複数行を含むファイルがあり、各行はファイルへのパスです。今、各行を各行とペアリングしたいと思います。その他ライン(自体ではない)。また、私の目的に応じて、ペアはペアとA B同じでB Aあるため、これらの組み合わせの1つだけを作成する必要があります。

はい

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
  • -0777フルファイルをフルルックにしてください(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


AND 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で置き換えることができます(ただし、GNUを使用しないと-1 2 -2 2置き換えることはできません)。-j2join

コマンド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) $ 

関連情報