web-dev-qa-db-ja.com

sedでbash変数を処理する

bash変数LATLNGには、緯度と経度の値がかっこで囲まれています。

_(53.3096,-6.28396)_

これらをLATおよびLONと呼ばれる変数に解析したいので、sedを介して実行しようとしています

LAT=$(sed "s/(\(.*\),\(.*\))/\1/g" "$LATLNG")
LON=$(sed "s/(\(.*\),\(.*\))/\2/g" "$LATLNG")

ただし、次のエラーが発生します。

sed: can't read (53.3096,-6.28396): No such file or directory

16
conorgriffin

これは純粋なシェル構文で解決できます。ただし、括弧(大括弧)があるため、一時変数は必要です。

#!/bin/bash

LATLNG="(53.3096,-6.28396)"

tmp=${LATLNG//[()]/}
LAT=${tmp%,*}
LNG=${tmp#*,}

または、IFSを使用してreadビルトインを使用することで、一度に実行できます。

#!/bin/bash

LATLNG="(53.3096,-6.28396)"

IFS='( ,)' read _ LAT LNG _ <<<"$LATLNG"
18
SiegeX

この特定のケースではSiegeXの回答の方が適していますが、sedに任意のテキストを渡す方法も知っておく必要があります。

sedは、2番目、3番目などのパラメーターとしてファイル名を想定しています。ファイル名が見つからない場合は、標準入力から読み取ります。したがって、処理したいテキストがファイルにない場合は、sedにパイプする必要があります。最も簡単な方法はこれです:

echo "blah blah" | sed 's/blah/blam/g'

したがって、あなたの例は次のようになります:

LAT=$(echo "$LATLNG" | sed 's/(\(.*\),\(.*\))/\1/g')
LON=$(echo "$LATLNG" | sed 's/(\(.*\),\(.*\))/\2/g')

代替(より良いがあいまいな)メソッド

あなたがその可能性があると思うなら$LATLNGはダッシュで始めることもできますが、詳細を知りたい場合は、printfの代わりにechoを使用する必要があります。

printf '%s' "$LATLNG" | sed 's/foo/bar/g'

または「ヒアドキュメント」ですが、使用している構成では少し扱いに​​くい場合があります。

LAT=$(sed 's/foo/bar/g' <<END
$LATLNG
END
)

または、bashを使用していて、移植性を気にしていない場合は、「こちらの文字列」を使用できます。

sed 's/foo/bar/g' <<< "$LATLNG"
23
Jander

以下は、あらゆるPOSIXシェルで機能するソリューションです。

parse_coordinates () {
  IFS='(), '  # Use these characters as Word separators
  set -f      # Disable globbing
  set $1      # Split $1 into separate words
  set +f      # Restore Shell state
  unset IFS
  LAT=$2      # $1 is the empty Word before the open parenthesis
  LON=$3
}
parse_coordinates "$LATLNG"

次に、使用されている特定の構文を解析する、同等に移植可能な別のソリューションを示します。

LAT=${LATLNG%\)}    # strip final parenthesis
LAT=${LAT#\(}       # strip initial parenthesis
LON=${LAT##*[, ]}   # set LON to everything after the last comma or space
LAT=${LAT%%[, ]*}   # set LAT to everything before the first comma or space