私はUNIXに初めて触れ、UNIXで基本レベルのテキスト処理を学ぶことを試みています。したがって、この質問は非常に基本的に見えるかもしれませんが、どんなガイドラインでも本当に感謝します。
次のテキストファイルがあります
A 1
B 2
C 9
D 1
A 5
B 3
C 4
A 6
C 7
A 5
C 1
このために、次のように助けを借りて命令を一つにまとめることができました。
cat | awk 'BEGIN{OFS=FS=" "}!(($1,$2)in c){c[$1,$2]=1;r[$1]=r[$1] OFS $2}
END{for(i in r){print i r[i]}}'
シェルスクリプトから次の形式に変換します。
A 1 5 6 5
B 2 3
C 9 4 7 1
D 1
私のシェルスクリプトはパラメータk(例:= 7)も受け入れます。
この場合、私のスクリプトは、合計7つの要素がサンプリングされるまで、各ボックス(A、B、C、D)から1つの要素をサンプリングする必要があります。次のように:まずAから1を選択し、次にBから2、Cから9、Dから1、Aから5、Bから3、Cから4を選択して表示します。
A 1 5
B 2 3
C 9 4
D 1
入力がk = 9の場合、出力は次のようになります。
A 1 5 6
B 2 3
C 9 4 7
D 1
ベストアンサー1
高級言語では配列の配列を使用できますが、bashにはそのような機能はありません。複数レベルのデータ構造に関連するこのような問題は、シェルで解決するのが非常に面倒なことがよくあります。
しかし、目標はPythonではなくUnixのテキスト処理を学ぶことですので、シェルで解決してみましょう。
このソリューションでは、ファイルを一度読み込んで行ヘッダーを取得し、複数回再読み込みして必要な数の要素を収集します。私たちは2つの配列を維持します。outrow
各行が私たちが行くところに追加される出力ライン配列cursor
と各行の位置を格納する整数配列です。
要求を満たすのに十分な要素がない場合、このスクリプトは永久に繰り返されます。この問題を解決することは、読者の練習課題として残されます。
#!/bin/bash
k=$1
input=input.txt
declare -a outrow
declare -a cursor
K=0
n=0
while read line
do
outrow[$n]=${line%% *}
cursor[$n]=1
(( n++ ))
done < $input
while [[ $K -lt $k ]]
do
n=0
while read line
do
declare -a col=( $line )
if [[ ${#col[@]} -gt ${cursor[$n]} ]]
then
outrow[$n]+=" ${col[ ${cursor[$n]} ]}"
(( cursor[$n]++ ))
(( K++ ))
[[ $K -lt $k ]] || break
fi
(( n++ ))
done < $input
done
for row in "${outrow[@]}"
do
echo "$row"
done