กำลังประมวลผลตัวแปร 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 บ้าง
Michael Dillon

คุณค่าเหล่านี้มาจากไหน มันจะมีประสิทธิภาพมากขึ้นในการแยกค่าละติจูดและลองจิจูดออกจากแหล่งต้นฉบับกว่าการเพิ่มขั้นตอนพิเศษโดยการใส่พวกเขาในbashตัวแปร
Kusalananda

คำตอบ:


18

สิ่งนี้สามารถแก้ไขได้ผ่านทางไวยากรณ์เปลือกบริสุทธิ์ มันต้องการตัวแปร temp เนื่องจากในวงเล็บ (วงเล็บ) แม้ว่า:

#!/bin/bash

LATLNG="(53.3096,-6.28396)"

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

อีกวิธีหนึ่งคุณสามารถทำได้ในครั้งเดียวโดยการเล่นIFSและใช้readbuiltin:

#!/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/…
Ricardo Stuven

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'

หรือเอกสาร "here here" แต่นั่นอาจเป็นเรื่องที่น่าอึดอัดใจเล็กน้อยกับสิ่งก่อสร้างที่คุณกำลังใช้:

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

หรือหากคุณใช้งานbashและไม่กังวลเรื่องการพกพาคุณสามารถใช้ "here string":

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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.