Xử lý biến bash với sed


16

biến bash LATLNG chứa giá trị vĩ độ & kinh độ trong ngoặc như vậy

(53.3096,-6.28396)

Tôi muốn phân tích chúng thành một biến gọi là LAT và LON mà tôi đang cố gắng thực hiện thông qua sed như vậy

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

Tuy nhiên, tôi nhận được lỗi sau:

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


1
Học một ngôn ngữ kịch bản như Python, Ruby, thậm chí là PERL, để bạn không phải ép vỏ làm mọi thứ cho bạn. Bạn thậm chí có thể có Javascript (Rhino) để chạy trên hệ thống UNIX và hầu như mọi người đều cần biết một số Javascript.
Michael Dillon

Những giá trị này đến từ đâu? Sẽ hiệu quả hơn khi phân tích các giá trị vĩ độ và kinh độ ra khỏi nguồn ban đầu hơn là thêm một bước bổ sung bằng cách đặt chúng vào một bashbiến.
Kusalananda

Câu trả lời:


18

Điều này có thể được giải quyết thông qua cú pháp shell thuần. Nó không yêu cầu biến temp vì dấu ngoặc đơn (ngoặc):

#!/bin/bash

LATLNG="(53.3096,-6.28396)"

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

Ngoài ra, bạn có thể làm điều đó trong một lần bằng cách chơi IFSvà sử dụng readnội dung:

#!/bin/bash

LATLNG="(53.3096,-6.28396)"

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

Ví dụ đầu tiên sẽ chỉ hoạt động trong bash, không phải trong vỏ POSIX.
gelraen

1
@gelraen do đó#!/bin/bash
SiegeX

Xem thêm bản mở rộng tại đây: gnu.org/software/bash/manual/ Kẻ
Ricardo Stuven

22

Câu trả lời của SiegeX tốt hơn cho trường hợp cụ thể này, nhưng bạn cũng nên biết cách chuyển văn bản tùy ý sang sed.

sedđang mong đợi tên tệp là tham số thứ hai, thứ ba, v.v. và nếu không tìm thấy tên tệp nào, nó sẽ đọc từ đầu vào tiêu chuẩn của nó. Vì vậy, nếu bạn có văn bản mà bạn muốn xử lý không có trong một tệp, bạn phải chuyển nó sang sed. Cách đơn giản nhất là đây:

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

Vì vậy, ví dụ của bạn sẽ trở thành:

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

Phương pháp thay thế (tốt hơn nhưng tối nghĩa hơn)

Nếu bạn nghĩ rằng có bất kỳ cơ hội nào $LATLNGcó thể bắt đầu bằng dấu gạch ngang hoặc nếu bạn muốn trở thành người phạm tội, bạn nên sử dụng printfthay vì echo:

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

Hoặc một "tài liệu ở đây", nhưng điều đó có thể hơi khó xử với cấu trúc bạn đang sử dụng:

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

Hoặc nếu bạn đang sử dụng bashvà không lo lắng về tính di động, bạn có thể sử dụng "chuỗi ở đây":

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

3

Đây là một giải pháp sẽ hoạt động trong mọi vỏ 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"

Đây là một giải pháp di động tương tự khác phân tích cú pháp cụ thể được sử dụng.

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

Bạn có lẽ nên làm set -- ...Có một cơ hội rất tốt nhân vật đầu tiên là a -.
mikeerv
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.