在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(设置为“导出”)andlocalare、 和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


以上是在shell脚本中的变量名之前插入“local”会导致错误的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>