Linux Bash脚本:参数的扩展不使用$@或$*
使用Linux Bash脚本:参数的扩展不使用$@或$*,linux,bash,shell,variable-expansion,brace-expansion,Linux,Bash,Shell,Variable Expansion,Brace Expansion,使用$@可以对bash中的文件列表执行操作。例如: script.sh: #!/bin/bash list=$@ for file in $list; do _commands_; done 然后我可以用 ~/path/to/./script dir1/{subdir1/*.dat,subdir2/*} 此参数将扩展为若干变为$list的参数。但是现在我想要其他参数,比如$1,$2,这个列表是$3。因此我希望dir1/{subdir1/*.dat,subdir2/*}的扩展发生在脚本内部,而
$@
可以对bash中的文件列表执行操作。例如:
script.sh:
#!/bin/bash
list=$@
for file in $list; do _commands_; done
然后我可以用
~/path/to/./script dir1/{subdir1/*.dat,subdir2/*}
此参数将扩展为若干变为$list
的参数。但是现在我想要其他参数,比如$1,$2,这个列表是$3。因此我希望dir1/{subdir1/*.dat,subdir2/*}
的扩展发生在脚本内部,而不是变成许多参数。在命令行上,可以执行以下操作:
find dir1/{subdir1/*.dat,subdir2/*}
并获得所需的输出,即一个if文件列表。所以我试过这样的方法:
arg1=$1
arg2=$2
list=$(find $3)
for file in $list; do _commands_; done
...
电话:
~/path/to/./script arg_1 arg_2 'dir1/{subdir1/*.dat,subdir2/*}'
但是没有成功。如果您能提供一些帮助,帮助您将此列表扩展为脚本中的变量,我们将不胜感激!:)
编辑:下面的答案给出了使用以下命令的解决方案:
arg1="$1"
arg2="$2"
shift 2
for f in "$@"; do echo "processing $f"; done;
但是出于好奇,是否仍然可以将字符串
dir1/{subdir1/*.dat,subdir2/*}
传递给脚本中的find
命令(或指向同一端的任何方法),而不使用$@
,并以这种方式获取列表?这可能很有用,例如,如果最好不要将列表作为第一个或最后一个参数,或者在某些其他情况下,即使它需要转义字符或引用参数。您可以在脚本中使用以下代码:
arg1="$1"
arg2="$2"
shift 2
for f in "$@"; do echo "processing $f"; done;
然后称之为:
~/path/to/script arg_1 arg_2 dir1/{subdir1/*.dat,subdir2/*}
使用shift 2
将位置参数移动2处,从而使$3
成为$1
和$4
成为$2
等。然后可以直接调用$@
来迭代其余参数
根据帮助移位:
shift: shift [n]
Shift positional parameters.
Rename the positional parameters $N+1,$N+2 ... to $1,$2 ... If N is
shell扩展是在调用脚本之前由shell执行的。这意味着您必须引用/转义参数。在脚本中,可以使用eval
执行扩展
#!/bin/bash
arg1="$1" ; shift
arg2="$2" ; shift
eval "list=($@)"
for q in "${list[@]}" ; do echo "$q" ; done
在您的示例中,我不认为在脚本内部进行扩展有什么意义
#!/bin/bash
arg1="$1" ; shift
arg2="$2" ; shift
list=("$@")
for q in "${list[@]}" ; do echo "$q" ; done
或者只是
#!/bin/bash
arg1="$1" ; shift
arg2="$2" ; shift
for q in "$@" ; do echo "$q" ; done
list=$@
不会将$@
复制到数组中list=(“$@”)
会,不过您需要将它扩展为“${list[@]}”中文件的
。当您的输入变得有趣(全局字符、空格等)时,以另一种方式进行操作将产生微妙(或不那么微妙)的错误。列表将列出具有相当好的名称的数据文件,因此这不应该是一个问题。尽管$list用于gnuplot调用,以在单个绘图中绘制列出的文件。使用“$list”中的[file]文件的plot…
和它现在得到的格式工作得很好。那么,这听起来很适合您的需要。不过,我要提醒您注意养成这样的习惯--我看到过TB的备份被删除,因为有人认为目录只有好的名称,然后缓冲区溢出创建了一个带有星号并用空格包围的文件。如果参数包含分号会怎么样。使用eval解析命令行参数是危险的,您没有给出任何指示。是的,您是对的。不需要在脚本内部展开。我错误地认为这是必然的:)非常感谢!检查了第一个答案;)我没有弄错(虽然我认为我是因为移位)。好吧,把这个作为第三个参数传递为“1”;ls;x=(1“
),看看happenst不是什么,因为它们被引用了。传递“1”;ls;x=(1”
将anubhava的脚本作为第三个arg,将您的脚本作为第三个arg,并查看差异。我想让您在回答中警告可能发生的情况,这样就不会有人潜在地(最坏情况下)这样做无意中破坏了他们的系统。这看起来很完美,不需要在命令行参数中转义字符或引用。不熟悉shift命令。非常感谢!
#!/bin/bash
arg1="$1" ; shift
arg2="$2" ; shift
for q in "$@" ; do echo "$q" ; done
$ ./a 123 456 a{b,c} d*
ab
ac
d.pl
docs