什么是表达式$ {*:1:$#:1}和$ {*:1:$# - 1}

时间:2016-02-03 15:02:56

标签: bash input parameters scripting

有人可以向我解释这些表达是什么意思吗?对我来说太难了解释:

$(*:1:$#:1)
$(*:1:$# - 1)

它们在脚本的开头使用:

!#/bin/bash
file=${*:1:$#:1}
egrep_command = `./generate_command $file ${*:1:$#-1}

我知道最后一个参数是一个文件的名称,我有兴趣激活所有其他参数的generate_command,从第一个参数到最后一个参数。有些人应该如何做我所说的,我不会理解整个语法。

1 个答案:

答案 0 :(得分:3)

有问题的语法是parameter expansion

给出的脚本正在尝试 - 严重错误 - 将其命令行上的最后一个变量分配给file,并传递其他变量。

下面是一个版本,其中最明显的战术(与战略相对)错误得到纠正(尽管有一些关于意图的假设,因为它无法分辨哪些错误的代码意图到意味着没有人类语言描述):

#!/bin/bash

# assign last variable in "$@" to file
# This is taking the very last item in the list, by starting at the position named by the
# total number of arguments
file=${@:$#}

# call generate_command with that file first, and all other arguments after
egrep_command=$(./generate_command "$file" "${@:1:$#-1}")

即使纠正了这些错误,这也是非常不明智的代码:如果它将命令存储在标量(字符串)变量中,它就容易出现所有错误在BashFAQ #50。 (如果打算使用eval解决其中一些问题,那么它也会引入安全漏洞。)

此外,在原始代码中使用引号内没有引号而不是$*的{​​{1}}将所有选定的参数与空格连接在一起 - 或者,如果设置了$@变量,则其第一个字符 - 在它们之间,然后每当IFS(或默认情况下,制表符,空格和换行符)中的任何字符存在时,将项目分成多个部分,将每个部分评估为全局模式。如果您不想完成所有这些逻辑,请不要使用IFS - 使用$*,并在引号内使用它(除了在上下文中,例如变量赋值,其中报价是不必要的。)

关注作为问题核心的PE:

$@从特殊数组"${@:start:len}"扩展到len项,从位置start开始。如果你有自己的数组,比如名为"$@",你可能会写一些与arr类似的内容。