値間の明示的な範囲

値間の明示的な範囲

bash魔法を使用してテキストファイルの2番目の列要素間の範囲を計算するきちんとした方法はありますか? (私は現在Pythonを使ってこれを行っています。)

入力:ファイル1

A   1-5
A   17-19
B   1-5
B   4-6

期待される出力:ファイル2

A   1,2,3,4,5,17,18,19
B   1,2,3,4,5,6    

編集する@Anthon:要素を蓄積するために、次のようなものを使用しています。次に、forループを使用して範囲を計算します。

d_pos= {} 
for row in open('File.txt'): 
    x, y = [ value.strip() for value in row.split('\t')] 
    if x in d_pos:        
        d_pos[x].append(y)    
    else:        
        d_pos[x] = [y]

ベストアンサー1

あなたが要求したように直接bashを使用します(しかし私はbash 4.0が必要な連想配列を使用しています)。

秘訣は中かっこシーケンスの拡張{x..y}、整数xの場合、yはすべて含まれている値の範囲([x、y]など)のテキストリストに展開されます。eval変数拡張の前に中かっこ拡張が発生するため、1つも追加する必要があります。

declare -A data seen  # explicit associative arrays
while read col range; do
   data[$col]="${data[$col]} $(eval echo {${range/-/..}})"
done <<DATA
A   1-5
A   17-19
B   1-5
B   4-6
DATA

# dump array
#declare -p data

for ii in ${!data[@]}; do
    seen=();  datum=""
    # build list of unique values
    for dd in ${data[$ii]}; do
        (( ${seen[$dd]:-0} )) || datum="$datum $dd"
        let seen[$dd]++
    done

    datum=${datum# }     # drop leading space
    datum=${datum// /,}  # spaces to commas
    printf "%-4s %s\n" "$ii" "$datum"
done

シーケンス拡張のバリエーションは、a{x..y}b拡張の各項目の前に「a」を追加し、「b」を追加することです。これを使用して「,」を追加し、必要に応じてデータ変数を変更できます。シーケンス拡張は1の増分を処理し、x> yの場合は-1を処理します。

出力をソートする必要があるかもしれません。反復連想配列のキーには明確に定義された順序がなく、入力範囲が事前にソートされているかどうかを明らかにしませんでした(したがって、コードが複雑すぎませんでした)。

おすすめ記事