Elaborazione della variabile bash con sed


16

bash variabile LATLNG contiene un valore di latitudine e longitudine tra parentesi in questo modo

(53.3096,-6.28396)

Voglio analizzarli in una variabile chiamata LAT e LON che sto cercando di fare tramite sed in questo modo

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

Tuttavia, ottengo il seguente errore:

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


1
Impara un linguaggio di scripting come Python, Ruby, forse anche PERL, in modo da non dover forzare la shell a fare tutto per te. Puoi anche far funzionare Javascript (Rhino) su un sistema UNIX e quasi tutti devono conoscere Javascript.
Michael Dillon,

Da dove vengono questi valori? Sarebbe più efficiente analizzare i valori di latitudine e longitudine dalla fonte originale piuttosto che aggiungere un ulteriore passaggio inserendoli in una bashvariabile.
Kusalananda

Risposte:


18

Questo può essere risolto tramite la sintassi della shell pura. Richiede una variabile temp a causa delle parentesi (parentesi) però:

#!/bin/bash

LATLNG="(53.3096,-6.28396)"

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

In alternativa, puoi farlo in una volta sola giocando IFSe usando il readbuiltin:

#!/bin/bash

LATLNG="(53.3096,-6.28396)"

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

Il primo esempio funzionerà solo in bash, non nella shell POSIX.
Gelraen,

1
@gelraen quindi il#!/bin/bash
SiegeX il

Vedi altre espansioni qui: gnu.org/software/bash/manual/…
Ricardo Stuven

22

La risposta di SiegeX è migliore per questo caso particolare, ma dovresti anche sapere come passare un testo arbitrario a sed.

sedsi aspetta nomi di file come secondo, terzo, ecc. parametri e, se non trova alcun nome di file, legge dal suo input standard. Quindi se hai del testo che vuoi elaborare che non è in un file, devi reindirizzarlo sed. Il modo più semplice è questo:

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

Quindi il tuo esempio diventerebbe:

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

Metodi alternativi (migliori ma più oscuri)

Se pensi che ci sia qualche possibilità che $LATLNGpossa iniziare con un trattino o se vuoi essere pedante, dovresti usare printfinvece di echo:

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

O un "documento qui", ma può essere un po 'imbarazzante con il costrutto che stai usando:

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

O se stai usando bashe non sei preoccupato per la portabilità, puoi usare una "stringa qui":

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

3

Ecco una soluzione che funzionerà in qualsiasi 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"

Ecco un'altra soluzione ugualmente portatile che analizza la sintassi specifica utilizzata.

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

-1
LATLNG="(53.3096,-6.28396)"
set ${LATLNG//[(,)]/ }
LAT=$1
LON=$2

Probabilmente dovresti farlo. set -- ...C'è una buona probabilità che il primo personaggio sia un -.
Mikeserv,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.