Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux Bash脚本:参数的扩展不使用$@或$*_Linux_Bash_Shell_Variable Expansion_Brace Expansion - Fatal编程技术网

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