用sed处理bash变量


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之类的脚本语言,这样您就不必强迫shell为您做所有事情。您甚至可以使Javascript(Rhino)在UNIX系统上运行,并且几乎每个人都需要了解一些Javascript。
迈克尔·狄龙

这些价值从何而来?从原始来源解析纬度和经度值比通过将其放入bash变量来增加额外的步骤效率更高。
库萨兰达

Answers:


18

这可以通过纯Shell语法解决。由于括号(括号)的原因,它确实需要一个临时变量:

#!/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 shell。
gelraen 2011年

1
@gelraen因此#!/bin/bash
SiegeX 2011年

在此处查看更多扩展信息: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 shell中使用的解决方案:

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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.