Обробка змінної bash з sed


16

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


1
Вивчіть мову сценаріїв на зразок Python, Ruby, можливо навіть PERL, так що вам не доведеться змушувати оболонку робити все за вас. Ви навіть можете змусити Javascript (Rhino) працювати в системі UNIX, і майже всі повинні знати деякі Javascript.
Майкл Діллон

Звідки беруться ці значення? Було б ефективніше розібрати значення широти та довготи з вихідного джерела, ніж додавати додатковий крок, поставивши їх у bashзмінну.
Кусалаланда

Відповіді:


18

Це можна вирішити за допомогою синтаксису чистої оболонки. Це вимагає змінної temp через дужки (дужки), хоча:

#!/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"

Перший приклад буде працювати лише в bash, а не в оболонці POSIX.
gelraen

1
@gelraen, отже#!/bin/bash
SiegeX

Дивіться більше розширень тут: gnu.org/software/bash/manual/…
Рікардо Стювен

22

Відповідь SiegeX краще для конкретного випадку, але ви також повинні знати, як передавати довільний текст sed.

sedочікує, що параметри файлів мають свою другу, третю, і т.д. Отже, якщо у вас є текст, який ви хочете обробити, який не є у файлі, вам доведеться передати його 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"

3

Ось рішення, яке буде працювати в будь-якій оболонці 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

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

Вам, мабуть, варто це зробити. set -- ...Є дуже хороший шанс, що перший персонаж - це -.
mikeserv
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.