【问题标题】:Interpolating variables which contain '$' in a bash script在 bash 脚本中插入包含“$”的变量
【发布时间】:2013-11-15 19:31:06
【问题描述】:

我正在编写一个创建用户帐户的 bash 脚本。用户名和密码哈希是根据特定标准从文件中提取的。密码哈希自然包含分隔哈希字段的“$”(例如 $1${SALT}$...)。

问题在于useradd 的 -p 选项需要在密码哈希周围加上单引号,以防止将“$”字段插入为变量。传递变量时,为了正确插入它,引号需要是双引号。单引号将变量视为字符串。

但是,如果我在双引号中传递变量,则变量会被扩展,然后每个“$”都被视为变量,这意味着永远不会正确设置密码。更糟糕的是,一些变量中包含大括号('{' 或 '}'),这进一步搞砸了事情。

我怎样才能传递这样一个值并确保它被完全插值而不被 shell 修改?

所有插值变量都完好无损的特定代码行示例:

# Determine the customer we are dealing with by extracting the acryonym from the FQDN
CUSTACRO=$(${GREP} "HOST" ${NETCONF} | ${AWK} -F "." '{print $2}')

# Convert Customer acronym to all caps
UCUSTACRO=$(${ECHO} ${CUSTACRO} | ${TR} [:lower:] [:upper:])

# Pull the custadmin account and password string from the cust_admins.txt file
PASSSTRING=$(${GREP} ${CUSTACRO} ${SRCDIR}/cust_admins.txt)

# Split the $PASSSTRING into the custadmin and corresponding password
CUSTADMIN=$(${ECHO} ${PASSSTRING} | ${CUT} -d'=' -f1)
PASS=$(${ECHO} ${PASSSTRING} | ${CUT} -d'=' -f2)

# Create the custadmin account
${USERADD} -u 20000 -c "${UCUSTACRO} Delivery Admin" -p "${PASS}" -G custadmins ${CUSTADMIN}

编辑:扩展代码以获得更多上下文。

【问题讨论】:

  • 您是否尝试过使用反斜杠转义?例如。使用 \' 或 \"
  • 您可以通过将set -x 放在相关命令之前(以及set +x 之后)来测试这样的脚本中发生了什么。这将使 shell 在执行之前打印每个命令。好吧,实际上,它会打印一个等效的命令——一个具有相同最终结果的命令,但可能具有不同(但等效)的引用/转义/等。这可以让您更好地了解实际发生的情况(一旦您习惯了等效位)。

标签: bash shell variables


【解决方案1】:

分配$PASS时使用单引号。双引号不会递归扩展变量。

观察:

$ foo=hello
$ bar=world
$ single='$foo$bar'
$ double="$foo$bar"
$ echo "$single"
$foo$bar
$ echo "$double"
helloworld

引号仅影响 shell 解析文字字符串的方式。只有当您根本不使用任何引号时,shell 才会查看变量“内部”,即便如此,它也只会进行分词和通配符扩展。

【讨论】:

  • 当使用命令扩展设置 $PASS 时这可能吗?我已经用所有设置数据的代码更新了问题。
  • 其实看起来你应该没有问题;哈希值绝不是普通数据。 (尽管你真的应该在所有这些变量和$()s 周围加上双引号,以防它们包含空格。)
  • 次要更正:在扩展一个根本不在引号中的变量后,shell 会进行分词和 glob(通配符)扩展。
  • @GordonDavisson 将永远不会停止奇迹。这就是我使用 zsh 的原因;)
猜你喜欢
  • 1970-01-01
  • 2013-02-25
  • 1970-01-01
  • 2012-12-02
  • 2013-11-19
  • 2018-02-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多