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