传递包含点的 bash 命令行参数

传递包含点的 bash 命令行参数

如何传递包含点 (.) 的命令行参数?是否有任何转义序列可以捕获像点这样的字符?

从 shell 调用以下 bash 脚本不起作用:

# ./deploy.sh input.txt
./deploy.sh: line 9: input.txt: syntax error in expression (error token is ".txt")

我已经尝试过以下方法:

  1. 反斜杠
  2. 引用
  3. 双引号
  4. ./deploy.sh 输入(这有效)

编辑

以这个用例为例:

  1. 我有3个文件: server.jar client.jar gui.jar
  2. 我需要将它们从源到目的地进行 scp
  3. 源目录:login1@host1:/home/xyz/deploy/
  4. 目标目录:login2@host2:/data/apps/env/software/binary/

解决方案:

  1. 从命令行读取要复制到数组中的工件
  2. 使用正确的目录前缀创建目标路径和源路径字符串
  3. 使用 for 循环来 scp 每个工件(找出路径)

这是执行 1 的简单脚本(将工件读入数组):

#!/bin/bash
declare -a artifacts
for i
do
artifacts[i]=$i
echo ${artifacts[i]}
done

执行1

-bash-3.00$ ./simple.sh arg1 arg2 arg3
arg1
arg2
arg3

执行2

-bash-3.00$ ./simple.sh arg1.txt arg2.txt arg3.txt
./simple.sh: line 7: arg1.txt: syntax error in expression (error token is ".txt")

答案1

您需要使用declare -A而不是declare -a.您显然使用带有任意字符串参数的关联数组作为索引,但declare -a仅适用于整数索引数组。 arg.txt不计算为有效整数,因此您的错误。

编辑

您似乎正在使用bash版本 3。不幸的是,关联数组直到版本 4 才可用。我建议您发布原始deploy.sh脚本的清理版本,其中删除了敏感的个人信息,以便您可以从其他人那里获得有关替代方法的想法。

编辑2

简单总结一下聊天中的一些交流:

对所有参数执行某些操作的最简单方法是使用循环迭代它们for

    for arg; do
        scp login1@host1:"$arg" login2@host2:/dest/
    done

请记住用双引号引用 的所有实例"$arg"。你做不是需要自己将参数放入数组中,因为它们已经存在于数组中$@,这是for当您不给出显式时默认使用的in list...

答案2

每当您尝试在需要数字的地方使用字符串时,都会发生该错误。

例如

$((input.txt))

将导致打印相同的错误。

在您的情况下,事实证明您正在分配给一个使用数字索引的数组。

jw013 正确解释您需要执行declare -A(大写A)才能使您的示例正常工作。

之所以:

当分配给数组元素时,通常会写

array[0]=foo
array[1]=bar

但你也可以写任何算术表达式作为关键,例如

array[0+0]=foo
array[1+0]=bar

所以外壳看到了

array[input.txt]=input.txt

尝试将其转换为类似的数字

$((input.txt))

和失败。

点令人困惑并且没有点的论证似乎有效的原因是

$((input))

实际上是一个有效的数字。

bash看到input,确定它是一个有效的变量名称,看到该变量未设置,并将其替换为0

将其与 进行比较input.txt,它不是有效的变量名称,因为变量名称不能包含点!

为了避免这种令人困惑的行为,您可以使用

set -u

那么每当您尝试使用不存在的变量时,您都会收到错误,例如

set -u
artifacts[arg1]=arg1

打印错误

scriptname: line number: arg1: unbound variable

相关内容