bashスクリプトを使用したGPS座標変換

bashスクリプトを使用したGPS座標変換

画像のEXIF情報出力である一部のGPS座標を特定の形式に変換する必要があります。

これは一般的な出力です。

exif:GPSLatitude: 10/1, 10/1, 10/1
exif:GPSLatitudeRef: N
exif:GPSLongitude: 10/1, 10/1, 10/1
exif:GPSLongitudeRef: E

これは私が得なければならない文字列です:

10 10 10N 10 10 10E

次のスクリプトを使用してこれを実行できました。

cat $somefile | sed "s/    /$nul/g" | sed "s/exif:GPSLatitudeRef: /$nul/g" | sed "s/exif:GPSLongitude:/$nul/g" | sed "s/exif:GPSLongitudeRef: /$nul/g" | sed "s/exif:GPSLatitude: /$nul/g" | sed "s/\/1/$nul/g" | sed "s/,/$nul/g" | tr -d '\n'

しかし、いくつかの画像の出力が次のように少し異なることに気づきました。

exif:GPSLatitude: 10/1, 10/1, 1099/100
exif:GPSLatitudeRef: N
exif:GPSLongitude: 10/1, 10/1, 1088/100
exif:GPSLongitudeRef: E

/1私は、および(おそらくa)が前の数字の分母であることを知っています/10/100/1000

次の要因を考えてみましょう。

  1. 高い精度は必要ないので、最後の数字の小数点以下の2桁を削除できます(例:代わりにすること1088/100ができます)。1010.88
  2. そんな正確さがあったらいいな
  3. 座標の最初の2つの数字(タイル分、つまり10/1 10/1:)にも小数点があるかどうかはわかりません。この場合、世界のさまざまな場所を指す座標の精度が完全に台無しになります。

計算を実行し、実際に小数を数値に置き換えるには、このスクリプトをどのように変更する必要がありますか(もう少しエレガントにできますか?)

答え1

これを行うのは非常に複雑ですsed。より適切なツールはawkまたはですbc。たとえば、bcadd anotherを使用して、sed入力を「;」で区切られた一連の式(10/1)と文字列( "")に変換しようとします。または改行文字のため、bcは次のように入力します。

10/1;" "; 10/1;" "; 1099/100
"N \n"
10/1;" "; 10/1;" "; 1088/100
"E \n"

bc各式が評価され、10.00 10.00 10.99N 10.00 10.00 10.88E必要に応じて出力されます。 sed | bc | trに必要なものは次のとおりです。

sed '1i\
scale=2
/Ref: /s/.$/"& \n"/
s/.*: //
s/,/;" ";/g
' | 
bc | tr -d '\n'

awkあるいは、すべてとsedコマンドを次のように置き換えることもできます。tr

awk '
NF==4 { for(i=2;i<=4;i++){
         split($i,x,"/")
         printf "%s%g",i==2?"":" ",x[1]/x[2]
        }
      }
NF==2 { printf "%s%s",$2,$1~/Lat/?" ":"\n" }'

これにより、4つのフィールド(スペースで区切られている)がある行を探し、フィールド2〜4の場合、フィールド$ i(たとえば、「1099/100」)を「/」文字の2つの部分に分割します。次に、%g一般的な数値形式(x [1] / x [2])を使用して、部分2に分割された部分1を印刷します。フィールド 2 の場合%sの項目はprintf何もなく置き換えられ、他の 2 つのフィールドではスペースで置き換えられます。これにより、出力の数字が区別されます。

2つのフィールド(NF = = 2)がある行の場合は2番目のフィールド($2)を印刷し、フィールド1に「Lat」パターンが含まれている場合はスペースを印刷し、それ以外の場合は改行を印刷します。

関連情報