从 shell 脚本 (bash) 的参数列表中删除最后一个参数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20398499/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Remove last argument from argument list of shell script (bash)
提问by Nordanfors
This question concerns a bash script that is run in automator osx. I am using automator actions to get and filter a bunch of file references from the finder. Then I append to that list the name of the parent folder, also via an automator action. Automator then feeds these arguments to an action called "run shell script". I am not sure exactly how automator invokes the script but the argument list looks like this when echoed with: echo "$@"
这个问题涉及在 automator osx 中运行的 bash 脚本。我正在使用自动操作从查找器中获取和过滤一堆文件引用。然后我也通过自动操作将父文件夹的名称附加到该列表中。Automator 然后将这些参数提供给名为“运行 shell 脚本”的操作。我不确定 automator 究竟是如何调用脚本的,但是当回显时参数列表看起来像这样:echo "$@"
/Volumes/G-Raid/Online/WAV_TEST/Testbok 50/01/01000 43-001.wav /Volumes/G-Raid/Online/WAV_TEST/Testbok 50/02/02000 43-002.wav /Volumes/G-Raid/Online/WAV_TEST/Testbok 50/03/03000 43-003.wav /Volumes/G-Raid/Online/WAV_TEST/Testbok 50
/Volumes/G-Raid/Online/WAV_TEST/Testbok 50/01/01000 43-001.wav /Volumes/G-Raid/Online/WAV_TEST/Testbok 50/02/02000 43-002.wav /Volumes/G-Raid /在线/WAV_TEST/Testbok 50/03/03000 43-003.wav /Volumes/G-Raid/Online/WAV_TEST/Testbok 50
In this case path to 3 files and a folder.
在这种情况下,路径为 3 个文件和一个文件夹。
In the shell script I launch an application called ripcheckc* with the args passed from automator minus the last argument(the folder) in the list.
在 shell 脚本中,我启动了一个名为 ripcheckc* 的应用程序,其中包含从 automator 传递的参数减去列表中的最后一个参数(文件夹)。
I use this to remove the last argument:
我用它来删除最后一个参数:
_args=( "$@" )
unset _args[${#_args[@]}-1]
And this is echo $_args
:
这是echo $_args
:
/Volumes/G-Raid/Online/WAV_TEST/Testbok 50/01/01000 43-001.wav /Volumes/G-Raid/Online/WAV_TEST/Testbok 50/02/02000 43-002.wav /Volumes/G-Raid/Online/WAV_TEST/Testbok 50/03/03000 43-003.wav
/Volumes/G-Raid/Online/WAV_TEST/Testbok 50/01/01000 43-001.wav /Volumes/G-Raid/Online/WAV_TEST/Testbok 50/02/02000 43-002.wav /Volumes/G-Raid /在线/WAV_TEST/Testbok 50/03/03000 43-003.wav
Same as before but without the folder.
和以前一样,但没有文件夹。
Now, if I run ripcheckc with "$@"
as argument it works (but fails later on because of that last path in the argument list) If I use ${_args[@]}
the application will just abort silently. When I echo $@
and _args
the output looks identical except for the last argument.
现在,如果我将 ripcheckc"$@"
作为参数运行,它可以工作(但由于参数列表中的最后一条路径,稍后会失败)如果我使用${_args[@]}
该应用程序,它将静默中止。当我回显时$@
,_args
除了最后一个参数外,输出看起来相同。
My question is - what is the difference between $@ and $_args that make the first valid input and the second not?
我的问题是 - $@ 和 $_args 使第一个有效输入和第二个无效输入有什么区别?
*The application is ripcheckc
*该应用程序是ripcheckc
I hope my question makes sense.
我希望我的问题是有道理的。
EDIT: Solved.
编辑:解决了。
采纳答案by devnull
Assuming that you already have an array
, you can say:
假设你已经有了array
,你可以说:
unset "array[${#array[@]}-1]"
For example, if your script contains:
例如,如果您的脚本包含:
array=( "$@" )
unset "array[${#array[@]}-1]" # Removes last element -- also see: help unset
for i in "${array[@]}"; do
echo "$i"
done
invoking it with: bash scriptname foo bar baz
produces:
调用它:bash scriptname foo bar baz
产生:
foo
bar
回答by starfry
I have used this bash
one-liner before
我以前用过这个bash
单线
set -- "${@:1:$(($#-1))}"
It sets the argument list to the current argument list, less the last argument.
它将参数列表设置为当前参数列表,减去最后一个参数。
How it works:
这个怎么运作:
$#
is the number of arguments$((...))
is an arithmetic expression, so$(($#-1))
is one less than the number of arguments.${variable:position:count}
is a substring expression: it extractscount
characters fromvariable
starting at position. In the special casewherevariable
is@
, which means the argument list, it extractscount
argumentsfrom the list beginning atposition
. Here,position
is1
for the first argument andcount
is one less than the number of arguments worked out previously.set -- arg1...argn
sets the argument listto the given arguments
$#
是参数的数量$((...))
是一个算术表达式,所以$(($#-1))
比参数的数量少一个。${variable:position:count}
是一个子字符串表达式:它count
从variable
位置开始提取字符。在is的特殊情况下,这意味着参数列表,它从从 开始的列表中提取参数。这里,是第一个参数,比之前计算出的参数数量少一个。variable
@
count
position
position
1
count
set -- arg1...argn
将参数列表设置为给定的参数
So the end result is that the argument list is replaced with a new list, where the new list is the original list except for the last argument.
所以最终的结果是参数列表被替换为一个新列表,其中新列表是除了最后一个参数之外的原始列表。
回答by chepner
You can also get all but the last argument with
你也可以得到除了最后一个参数之外的所有参数
"${@:0:$#}"
which, honestly, is a little sketchy, since it seems to be (ab)using the fact that arguments are numbered starting with 1, not 0.
老实说,这有点粗略,因为它似乎(ab)使用了这样一个事实,即参数从 1 开始编号,而不是从 0 开始。
Update: This only works due to a bug (fixed in 4.1.2 at the latest) in handling $@
. It works in version 3.2.
更新:这仅由于处理$@
. 它适用于 3.2 版。