从 shell 脚本 (bash) 的参数列表中删除最后一个参数
Posted
技术标签:
【中文标题】从 shell 脚本 (bash) 的参数列表中删除最后一个参数【英文标题】:Remove last argument from argument list of shell script (bash) 【发布时间】:2013-12-22 07:19:13 【问题描述】:这个问题涉及在 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/在线/WAV_TEST/Testbok 50/03/03000 43-003.wav /Volumes/G-Raid/Online/WAV_TEST/Testbok 50
在这种情况下是 3 个文件和一个文件夹的路径。
在 shell 脚本中,我启动了一个名为 ripcheckc* 的应用程序,它使用从 automator 传递的参数减去列表中的最后一个参数(文件夹)。
我用它来删除最后一个参数:
_args=( "$@" )
unset _args[$#_args[@]-1]
这是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/在线/WAV_TEST/Testbok 50/03/03000 43-003.wav
和以前一样,但没有文件夹。
现在,如果我使用 "$@"
作为参数运行 ripcheckc,它可以工作(但由于参数列表中的最后一个路径而稍后失败)如果我使用 $_args[@]
,应用程序将静默中止。当我回显$@
和_args
时,除了最后一个参数外,输出看起来相同。
我的问题是 - 使第一个有效输入和第二个无效输入的 $@ 和 $_args 之间有什么区别?
*申请是ripcheckc
我希望我的问题有意义。
编辑:已解决。
【问题讨论】:
我用双引号解决了这个问题。像这样:ripcheckc "$_args[@]". 【参考方案1】:假设你已经有一个array
,你可以说:
unset "array[$#array[@]-1]"
例如,如果您的脚本包含:
array=( "$@" )
unset "array[$#array[@]-1]" # Removes last element -- also see: help unset
for i in "$array[@]"; do
echo "$i"
done
使用:bash scriptname foo bar baz
调用它会产生:
foo
bar
【讨论】:
谢谢,这是摆脱最后一个参数的更好方法。我的问题是,与 $array 相比,$@ 似乎有些不同,它将它作为我传递给它的应用程序的有效输入。我只是不知道它是什么。 @user1047256 尝试将$array[@]
传递给您的应用程序。
我尝试了你的建议,但还是不行。仅供参考,我将昵称更改为 Nordanfors。 :-)
@Nordanfors 总是引用变量。
应该接受下一个答案,而不是这个。它有三倍的赞成票。【参考方案2】:
你也可以得到除最后一个参数之外的所有参数
"$@:0:$#"
老实说,这有点粗略,因为它似乎(ab)使用了参数从 1 开始编号的事实,而不是 0。
更新:这只适用于处理$@
的错误(最迟在 4.1.2 中修复)。它适用于 3.2 版。
【讨论】:
代码"$@:1:$#-1"
正是使完整的参数列表像 "$@" 没有最后一个的原因。
对。粗略部分使用 0 作为第一个参数,以避免必须从第二个参数中减去 1。
实际上,索引 0 包括非参数 - 正在执行的脚本的路径(shell 自动提供的值)。您并没有避免减 1 - 最后一个参数仍然包含在内,您必须减去 1。使用 0 只是在列表中再添加一个(可能不需要)值。
由于随后修复了一个错误,这似乎在 bash
3.2 中有效。【参考方案3】:
我之前用过这个bash
one-liner
set -- "$@:1:$(($#-1))"
它将参数列表设置为当前参数列表,减去最后一个参数。
它是如何工作的:
$#
是参数的数量
$((...))
是一个算术表达式,因此 $(($#-1))
比参数数量少一。
$variable:position:count
是一个substring expression:它从variable
中提取count
字符,从位置开始。在special case 中,其中variable
是@
,表示参数列表,它从position
开始的列表中提取count
arguments。这里,position
是第一个参数的 1
,count
比之前计算的参数数量少一个。
set -- arg1...argn
sets the argument list 到给定的参数
所以最终结果是参数列表被替换为新列表,其中新列表是除最后一个参数之外的原始列表。
【讨论】:
简洁优雅:我喜欢。我使用下面@chepner 建议的变体来“删除”前两个参数,以便正确生成子流程:spawnProc "$@:3:$#"。不可否认,这是由于 BASH 的根源。它既优雅又简单。 我可以要求播放这个东西吗? @StevenLu 我已经修改了答案,以便为您提供解释。我希望它有所帮助。 太完美了!以上是关于从 shell 脚本 (bash) 的参数列表中删除最后一个参数的主要内容,如果未能解决你的问题,请参考以下文章