ファイルの各行から k までの要素を抽出します。

ファイルの各行から k までの要素を抽出します。

私は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

おすすめ記事