Sed ile bash değişkeni işleniyor


16

bash değişkeni LATLNG, bu şekilde parantez içinde bir enlem ve boylam değeri içerir

(53.3096,-6.28396)

Bunları sed gibi yapmaya çalıştığım LAT ve LON adlı bir değişkene ayrıştırmak istiyorum

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

Ancak, aşağıdaki hatayı alıyorum:

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


1
Python, Ruby, hatta PERL gibi bir betik dili öğrenin, böylece kabuğu sizin için her şeyi yapmaya zorlamak zorunda kalmazsınız. Hatta bir UNIX sistemi üzerinde Javascript (Rhino) çalıştırmak için alabilirsiniz ve neredeyse herkes bazı Javascript bilmek gerekir.
Michael Dillon

Bu değerler nereden geliyor? Enlem ve boylam değerlerini orijinal kaynağından ayrıştırmak, bir bashdeğişkene ekleyerek fazladan bir adım eklemekten daha etkili olur .
Kusalananda

Yanıtlar:


18

Bu, saf kabuk sözdizimi ile çözülebilir. Parantez (parantez) nedeniyle bir temp değişkeni gerektirir, ancak:

#!/bin/bash

LATLNG="(53.3096,-6.28396)"

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

Alternatif olarak, yerleşik ile oynayarak IFSve kullanarak tek seferde yapabilirsiniz read:

#!/bin/bash

LATLNG="(53.3096,-6.28396)"

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

İlk örnek POSIX kabuğunda değil, yalnızca bash ile çalışır.
gelraen

1
@gelraen dolayısıyla#!/bin/bash
SiegeX

Burada daha fazla genişletmeye bakın: gnu.org/software/bash/manual/…
Ricardo Stuven

22

SiegeX'in cevabı bu özel durum için daha iyidir, ancak keyfi metni nasıl aktaracağınızı da bilmelisiniz sed.

seddosya adlarını ikinci, üçüncü vb. parametreleri olarak bekliyor ve dosya adı bulamazsa, standart girdisinden okuyor. Bu nedenle, işlemek istediğiniz bir dosyada bulunmayan bir metniniz varsa, bunu bir araya getirmeniz gerekir sed. En basit yol şudur:

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

Böylece örneğiniz:

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

Alternatif (daha iyi ama daha belirsiz) Yöntemler

Eğer herhangi bir şansı var mı varsa $LATLNGbir tire ile başlayabilir ya da bilgiçlik olmak istiyorsanız, kullanmanız gereken printfyerine echo:

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

Veya bir "burada belge", ancak bu kullandığınız yapı ile biraz garip olabilir:

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

Veya bashtaşınabilirlik konusunda endişe duymuyorsanız "here string" i kullanabilirsiniz:

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

3

İşte herhangi bir POSIX kabuğunda çalışacak bir çözüm:

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"

Burada, kullanılan söz dizimini ayrıştıran eşit derecede taşınabilir başka bir çözüm var.

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

Muhtemelen yapmalısınız set -- ...İlk karakterin çok iyi bir şansı vardır -.
mikeserv
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.