从 unix shellscript 中读取位置参数时 $ 符号的问题

Joh*_*ohn 2 shell-script quoting variable

我编写了以下脚本:

#!/bin/bash

TEST=$1
TEST_1=$2

if [[ "$TEST" == e ]];then
echo $TEST_1
else
echo "Input is not e"
fi
Run Code Online (Sandbox Code Playgroud)

现在,如果我要跑:

sh test.sh e NS3#$xX$56M
Run Code Online (Sandbox Code Playgroud)

然后输出将是

NS3#56M
Run Code Online (Sandbox Code Playgroud)

这就是删除所有$xX$字符。有什么办法可以获得包括特殊字符在内的所有字符吗?

Adm*_*Bee 11

原因是您没有正确引用您的输入。您传递给脚本$的参数包含,并且您传递的参数不带引号(即简单地作为NS3#$xX$56M),这意味着它将受到变量扩展的影响。这意味着解释你的 shell

sh test.sh e NS3#$xX$56M
Run Code Online (Sandbox Code Playgroud)

调用test.sh脚本的命令将首先尝试$xX用 shell 变量的内容(本地定义或导出为环境变量)xX替换该部分,并且 - 因为可能没有 - 在它之前用“无”替换这部分将结果传递给您的脚本。但是,这是 shell 的正确功能,因此您的脚本基本上没有任何问题(如@roaima 所述)。

为防止出现此问题,请将字符串括在单引号中,这将禁用任何扩展:

sh test.sh e 'NS3#$xX$56M'
Run Code Online (Sandbox Code Playgroud)

作为脚本的一般说明:

  • 不要使用全大写的变量名,除非您计划将它们导出到环境中(即使用test而不是TEST) - 这可以防止脚本变量与可能的基本环境变量之间发生不必要的冲突。
  • 使用shellcheck,也可在许多 Linux 发行版上作为独立程序使用,以“校对”您的脚本;这将有助于防止许多错误。
  • 正如您从您遇到的问题中看到的那样,在使用shell 变量始终确保正确引用它们,除非您确定要进行变量/全局扩展和分词。这也适用于脚本中 shell 变量的使用。
  • 您将脚本称为
    sh test.sh ....
    
    Run Code Online (Sandbox Code Playgroud) 这将覆盖#!-line 并使用shshell,它在许多系统上将是不理解[[ ... ]]运算符的 POSIX 兼容 shell,例如要么使其可执行并将其调用为./test.sh,要么明确使用bash test.sh.

  • @John 那是不可能的。您无法从`NS3#M` 恢复`NS3#$xX$56M`。您需要修复使用无效参数调用脚本的任何内容。 (7认同)
  • 如果调用您的脚本的内容类似于 `system("sh test.sh " + someVar)`,那么该系统调用很可能正在使用 /bin/sh 来调用传递的字符串,因此您会得到 `sh -c 'sh test .sh NS3#$xX$56M'`。看看你是否可以做类似 `system(['bash', 'test.sh', someVar])` 这样的事情,它可以避免封闭 /bin/sh 并保持值不变。 (5认同)
  • @John,如果您的代码只是将输入替换到命令行,则暗示存在严重的安全错误——想想“Western Digital MyBooks 本周被黑客入侵的两种方式之一”类型的严重错误。真的,_真的_不要使用字符串连接将数据合并到 shell 命令中;任何正在做的事情都不应该被公之于众,而且你有足够的理由坚持让维护该组件的任何团队修复它,即使它不是你个人控制的代码。 (2认同)