Processando variável bash com sed

12

Variável bash LATLNG contém uma latitude & valor de longitude entre parênteses, como assim

(53.3096,-6.28396)

Eu quero analisá-los em uma variável chamada LAT e LON que estou tentando fazer via sed como assim

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

No entanto, recebo o seguinte erro:

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

Eu obviamente estou fazendo algo bobo aqui, mas é muito tarde e não consigo ver o que é. Eu tentei várias outras variações sem sorte também.

    
por conorgriffin 29.01.2011 / 07:51

4 respostas

17

Isto pode ser resolvido através da sintaxe pura da shell. Isso requer uma variável temporária por causa dos parênteses (colchetes) embora:

#!/bin/bash

LATLNG="(53.3096,-6.28396)"

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

Alternativamente, você pode fazer isso de uma só vez, jogando com IFS e usando o read builtin:

#!/bin/bash

LATLNG="(53.3096,-6.28396)"

IFS='( ,)' read _ LAT LNG _ <<<"$LATLNG"
    
por 29.01.2011 / 07:56
18

A resposta de SiegeX é melhor para este caso em particular, mas você também deve saber como passar um texto arbitrário para sed .

sed está esperando nomes de arquivos como seus segundo, terceiro, etc. parâmetros, e se ele não encontrar nenhum nome de arquivo, ele lê a partir de sua entrada padrão. Então, se você tem o texto que deseja processar que não está em um arquivo, é necessário canalizá-lo para sed . A maneira mais direta é esta:

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

Assim, seu exemplo se tornaria:

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

Métodos alternativos (melhor, mas mais obscuros)

Se você acha que há uma chance de que $LATLNG comece com um traço ou se você quiser ser pedante, use printf em vez de echo :

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

Ou um "documento aqui", mas isso pode ser um pouco estranho com a construção que você está usando:

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

Ou se você estiver usando bash e não estiver preocupado com a portabilidade, pode usar uma "string aqui":

sed 's/foo/bar/g' <<< "$LATLNG"
    
por 29.01.2011 / 09:00
3

Aqui está uma solução que funcionará em qualquer shell 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"

Aqui está outra solução igualmente portátil que analisa a sintaxe específica usada.

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
    
por 29.01.2011 / 13:31
-1
LATLNG="(53.3096,-6.28396)"
set ${LATLNG//[(,)]/ }
LAT=$1
LON=$2
    
por 19.06.2014 / 09:08