各ファイルには6つの列が含まれています(行数は異なる場合があります)。簡単な例を見てください:
1 0 0 0 0 0
0 1 1 1 0 0
私はどのように多くの一意の列(数字や一致する順序など)を確認したいと思います。この場合は3です。
これを行うための簡単な1行のコードはありますか?ある列を別の列と比較するのは簡単ですが、同じ列を見つける方法は何ですか?
答え1
次のパイプラインを使用して一意の列を計算できます。
$ awk '{for (i=1; i<=NF; ++i) a[i]=a[i]$i; } END { for (i in a) print a[i] }' foo \
| sort -u | wc -l
awkコマンドは入力を転置し、一意の行のみを維持しながら結果行をソートし(-u
)、最後にすべての(固有の)行(つまり、転置された列)の数を数えます(wc -l
)。
これはNF
組み込み awk 変数で、現在のレコードのフィールド数に自動的に設定されます。$i
i番目のフィールドを参照して、END
すべてのレコード処理が完了した後に実行されるように、次のブロックを保護します。 awk は、デフォルトでは空白と空白ではなく、フィールド区切りを使用します。
答え2
(((...))) しかし、同じ列を見つける方法は?
$ printf '%s\n' '1 0 0 0 0 0' '0 1 1 1 0 0' | awk -vSUBSEP='=' '
{ for (i=1; i<NF; i++)
for (j=i+1; j<=NF; j++)
if ($i==$j)
M[i,j]++
}
END{ for (m in M) if (M[m]==NR) print m }'
5=6
2=3
2=4
3=4
i<j
各行のすべての列について、その列のM[i,j]
値が等しい場合は常に増加します。したがって、行をM[i,j]==NR
読み取った後は、読み取っNR
たすべての行に対して値が同じになります。
答え3
この質問は私に多くの関心を持っていますが、私が正確に知らない部分に近づいて良い助けを得たいと思います。別の質問で投稿した後。私が投稿した質問を見ると、私が従う方法を理解できます。
この問題には2つの解決策があります(その1つグヌークス正解は真珠ソリューションとは異なるソリューション ジョーンズ私のソリューションと組み合わせたソリューション)。
#The variable appended_input will remove spaces/tabs and just append the rows.
#Modify the file name in this line. Here I use inputfile as the filename.
appended_input=$(column -s '\t' inputfile | tr -d '[:space:]') ;
#The array variable will store each column-wise value as an array element.
#I use sort to find the number of unique elements.
array=($(
for ((i=0; i<6; i++))
do
new=${appended_input:$i:1}
for ((j=i+6; j<${#appended_input}; j=j+6))
do
new="$new${appended_input:$j:1}"
done
echo "$new"
done
)) | echo "${array[@]}" | tr ' ' '\n' | sort -u | tr '\n' ' '
テスト
私の入力ファイルは次のとおりです。
1 0 0 1 0 0
0 1 1 0 0 0
1 1 1 1 1 0
1 0 0 1 0 1
1 0 0 1 0 1
上記のスクリプトを実行した後に得た結果は次のとおりです。
00011 00100 01100 10111
aを最後にパイプすると、wc -w
上記のように一意の列値の代わりに4のみが出力されます。
答え4
以下は、gawk
コプロセスを使用して各列を別々のインスタンスに供給し、一意のハッシュの合計数をsha256sum
報告するソリューションです(ハッシュの競合の可能性がsha256sum
統計的に有意ではないことを考慮すると、固有のハッシュの数は同じ固有の列と一致する必要があります)。 。数量)。一部の人々はこれを深刻なハッキングだと思うかもしれませんが、他の方法と比較してこのアプローチの1つの利点は、データを接続/転置しようとしないため、比較的メモリ効率が高いことです。
awk 'BEGIN{for(i=1; i<=6; ++i){s=sprintf("%*s", i+1, ""); a[i]="sha256sum"s}}
{for (i=1; i<=6; ++i) print $i |& a[i]}
END{com= "sort | uniq | wc -l"
for (i=1; i<=6; ++i){close(a[i], "to"); a[i] |& getline x;
close(a[i]); print x | com};
close(com)}' file