使用 sed 处理 bash 变量

使用 sed 处理 bash 变量

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

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"

答案2

这可以通过纯 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"

答案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

答案4

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

相关内容