在shell脚本中的变量名之前插入“local”会导致错误
这段代码(它是 shell 函数的一部分)完美运行:
output=$(
cat "${vim_file}" |
sed -rne "${EXTRACT_ENTITIES}" |
sed -re "${CLEAR_LEADING_QUOTES}" |
sed -re "${NORMALIZE_NAMES}"
)
但是当我试图在作业前插入“本地”这个词时……
local output=$(
cat "${vim_file}" |
sed -rne "${EXTRACT_ENTITIES}" |
sed -re "${CLEAR_LEADING_QUOTES}" |
sed -re "${NORMALIZE_NAMES}"
)
...我收到一个奇怪的错误:
local: commands.: bad variable name
代码中没有错误的不可见字符:只有制表符在其他地方缩进和空格。该脚本以“#!/bin/sh”开头。在函数中的其他变量之前插入“local”不会导致任何问题。用另一个任意字符串替换“输出”(变量名)不会有任何改变。操作系统是Linux。
回答
非常简短的回答:使用更多引号!
local output="$(
cat "${vim_file}" |
sed -rne "${EXTRACT_ENTITIES}" |
sed -re "${CLEAR_LEADING_QUOTES}" |
sed -re "${NORMALIZE_NAMES}"
)"
更长的答案:双引号变量引用和命令替换几乎总是一个好主意。双引号可以防止它们受到分词和文件名通配符扩展的影响,这很少是您想要的,并且可能会导致混淆问题。
在某些情况下,不使用双引号是安全的,但规则令人困惑且难以记住,并且容易出错。这是那些令人困惑的案例之一。不发生分词和通配符扩展的情况之一(因此可以安全地关闭双引号)是在赋值的右侧:
var=$othervar # safe to omit double-quotes
var2=$(somecommand) # also safe
var="$othervar" # this also works fine
var2="$(somecommand)" # so does this
一些 shell 将此扩展到作为命令一部分的赋值,例如localor export:
export var=$othervar # *Maybe* ok, depending on the shell
local var2=$(somecommand) # also *maybe* ok
bash 将这些视为一种赋值,因此它不会对值执行拆分扩展操作。但是 dash 更像是一个常规命令(其中参数确实被拆分扩展),因此如果您的脚本在 dash 下运行,它可能会出现这样的问题。
例如,假设somecommand打印“export 和 local 是 shell 命令”。然后在破折号中,local var2=$(somecommand)将扩展为:
local var2=export and local are shell commands.
...这将声明局部变量var2(设置为“导出”)and、local、are、 和shell。它还会尝试声明commands.为局部变量,但失败了,因为它不是合法的变量名。
因此,请使用更多引号!
export var="$othervar" # Safe in all shells
local var2="$(somecommand)" # also safe
或者分开声明(或两者兼而有之!):
export var
var=$othervar # Safe in all shells, with or without quotes
local var2
var2=$(somecommand) # also safe, with or without quotes