/bin/sh: 通配符扩展在脚本中不起作用

400*_*Cat 5 shell dash wildcards

我正在使用dash作为/bin/sh. 在我的脚本中,我有以下几行:

SSH_AUTH_SOCK=/tmp/ssh-????????????/agent.*
Run Code Online (Sandbox Code Playgroud)

哪个应该匹配 file /tmp/ssh-abcdefghijkl/agent.1234。即使文件存在,脚本也不会扩展模式,而是变量包含文字模式:

echo $SSH_AUTH_SOCK
/tmp/ssh-????????????/agent.*
Run Code Online (Sandbox Code Playgroud)

但是当我从命令行做同样的事情时,它扩展了模式:

sh -c 'SSH_AUTH_SOCK=/tmp/ssh-????????????/agent.* ; echo $SSH_AUTH_SOCK'
/tmp/ssh-abcdefghijkl/agent.1234
Run Code Online (Sandbox Code Playgroud)

为什么模式扩展(通配符匹配)在我的脚本中不起作用?

Kus*_*nda 12

文件名通配不会发生在像这样的分配中

SSH_AUTH_SOCK=/tmp/ssh-????????????/agent.*
Run Code Online (Sandbox Code Playgroud)

在您的代码似乎可以正常工作的地方,您会得到预期的输出,因为您没有引用$SSH_AUTH_SOCK. 您的sh -c脚本正在做的是将文字字符串分配/tmp/ssh-????????????/agent.*SSH_AUTH_SOCK,然后当您使用不带引号的变量时,shell 应用通配符echo

当您在命令行上尝试(echo $SSH_AUTH_SOCK打印文字模式)时它的行为方式不同的原因可能是因为您可能正在使用zshshell(它以不同的方式执行这些操作),或者您已set -f在 shell 中使用关闭文件名通配符,或者根本没有匹配的路径名。

如果你想做一些你提议的事情,那么使用

set -- /tmp/ssh-????????????/agent.*
SSH_AUTH_SOCK=$1
Run Code Online (Sandbox Code Playgroud)

这首先将位置参数设置为与给定模式匹配的所有路径名(按词法顺序)。然后它将这些路径名中的第一个分配给变量SSH_AUTH_SOCK

如果没有路径名与模式匹配,则模式将保持未扩展状态,稍后按原样分配给变量。

bashshell 中,您可以使用命名数组代替位置参数:

names=( /tmp/ssh-????????????/agent.* )
SSH_AUTH_SOCK=${names[0]}
Run Code Online (Sandbox Code Playgroud)

  • 请记住,在 sh 或 bash 中,如果 glob 与任何文件都不匹配,则模式将保持未扩展(在 bash 中,可以使用 `failglob` 或 `nullglob` 选项来避免这种情况。另见 `N` `zsh` 中的 glob 限定符或 ksh93 中的 `~(N)` glob 运算符)。 (2认同)
  • @TobySpeight 用户在脚本中使用 `dash`,是的。目前还不清楚他们正在测试的交互式 shell 是什么(他们的中间代码部分)。我在最后提到的“bash”只是一个额外的补充。 (2认同)