当包含空格时,为什么 glob 或大括号从变量扩展到数组是不可能的



我正在尝试使用从变量到数组的内部 bash glob 和大括号扩展机制。

path='./tmp2/tmp23/*'
expanded=($(eval echo "$(printf "%q" "${path}")"))

结果:

declare -- path="./tmp2/tmp23/*"
declare -a expanded=([0]="./tmp2/tmp23/testfile" [1]="./tmp2/tmp23/testfile2" [2]="./tmp2/tmp23/testfile3" [3]="./tmp2/tmp23/testfile4" [4]="./tmp2/tmp23/tmp231")

这是有效的。 (我在 ./tmp2/tmp23 文件夹中有 4 个文件 testfileX 和 1 个文件夹( 数组索引中的每个文件/文件夹。

现在,如果我的路径包含空格:

path='./tmp2/tmp2 3/*'
expanded=($(eval echo "$(printf "%q" "${path}")"))

结果

declare -- path="./tmp2/tmp2 3/*"
declare -a expanded=([0]="./tmp2/tmp2" [1]="3/")

由于 IFS 髑髅地,不工作什么都不会扩展,路径被拆分。

现在使用相同的路径包含空格但没有 glob:

path='./tmp2/tmp2 3/'
expanded=($(eval echo "$(printf "%q" "${path}"*)")) => added glob here outside ""

结果:

declare -a expanded=([0]="./tmp2/tmp2" [1]="3/testfile./tmp2/tmp2" [2]="3/testfile2./tmp2/tmp2" [3]="3/testfile3./tmp2/tmp2" [4]="3/testfile4./tmp2/tmp2" [5]="3/tmp231")

路径已扩展,但由于 IFS 导致结果为假和拆分。

现在带有报价的 $(eval(

expanded=("$(eval echo "$(printf "%q" "${path}"*)")")

结果:

declare -a expanded=([0]="./tmp2/tmp2 3/testfile./tmp2/tmp2 3/testfile2./tmp2/tmp2 3/testfile3./tmp2/tmp2 3/testfile4./tmp2/tmp2 3/tmp231")

现在,所有扩展都在同一个数组索引中完成。

如果没有空间,为什么 glob 或大括号扩展在变量内工作?

为什么当有空间时这不再起作用。完全相同的代码,但只是一个空格。球体或大括号扩展需要在双引号之外。评估似乎没有任何效果。

是否有任何其他替代方法可以使用(作为读取或映射文件,或者是否可以转义空格字符(?

我发现了这个问题 如何分配一个球体表达式 到一个变量 在 bash-脚本中,但没有关于空格的信息。

有没有办法将包含 glob 或大括号扩展参数的变量扩展到数组,当它们包含空格时,使用相同的方法而不进行单词拆分?

亲切问候

不要使用eval.不要使用子外壳。只是清除IFS.

path='./tmp2/tmp2 3/*'
oIFS=${IFS:-$' tn'} IFS='' # backup prior IFS value
expanded=( $path )           # perform expansion, unquoted
IFS=$oIFS                    # reset to original value, or an equivalent thereto

执行不带引号的扩展时,将按顺序发生两个单独的操作:

  • $IFS变量中找到的所有字符都用于将字符串拆分为单词
  • 然后,每个单词都扩展为一个单独的 glob。

默认值IFS包含空格、制表符和换行符。如果您不希望将空格、制表符和换行符视为单词之间的分隔符,则需要修改该默认值。

最新更新