在bash中删除命令的最后一个位置参数

4

我有一个叫做dosmt的脚本,我会输入一些参数并打印一些内容:

if [ "${@: -1}" == "--ut" ]; then
    echo "Hi"
fi

我想做的是,如果条件为真,则删除最后一个位置参数--ut。因此,如果我的输入是$ dosmt hello there --ut,它将回显Hi,但如果我在之后打印args,我只想保留hello there。所以基本上我想永久删除最后一个参数,我尝试使用shift,但那只是临时的,所以不起作用...

1
顺便提一下,在 [ ] 中使用 == 不能保证 POSIX 能够正常工作;标准提供的唯一字符串比较运算符是 =。请参阅 http://pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html。 - Charles Duffy
1
另外一件事是,传统的UNIX方法只允许在命令的前面,在位置参数之前使用--utc等选项,以便它们始终可以被移除;允许它们出现在任何地方是GNU的一种特性。 - Charles Duffy
1
请查看http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap12.html中的第9条和第10条指南。 - Charles Duffy
1
@mklement0: ls * -l可以正常工作,除非使用了--,但为了防止处理以破折号开头的文件名时出现意外行为,编写供健壮脚本使用/调用的工具的人应该使用--。 因此,ls -l -- *是正确的方法,允许以这种方式使用--可保留工具从足够谨慎的脚本中被调用的功能。 设计一个调用约定以防止遵循最佳实践的行为是失败设计。 - Charles Duffy
2
@CharlesDuffy:同意;让我来总结一下:虽然GNU工具允许您自由混合选项和操作数,但将所有选项放在操作数之前并使用“--”明确表示所有剩余参数应被视为操作数(而不是选项)是一个好习惯。 - mklement0
显示剩余3条评论
1个回答

7

首先,让我们设置你想要的参数:

$ set -- hello there --ut

我们可以验证参数是否正确:
$ echo "$@"
hello there --ut

现在,让我们移除最后一个值:

$ set -- "${@: 1: $#-1}"

我们可以验证最后一个值已成功被移除:
$ echo "$@"
hello there

脚本演示

为了在脚本中演示这个功能:

$ cat script
#!/bin/bash
echo Initial values="$@"
set -- "${@: 1: $#-1}"
echo Final values="$@"

我们可以使用您提供的参数运行:
$ script hello there --ut
Initial values=hello there --ut
Final values=hello there

@CharlesDuffy 非常好,谢谢你指出引用的问题。 - John1024
++; @CharlesDuffy:关于您已删除的答案中的“${@:0}”的说法最好远离索引0,其中之一是因为Bash 3.x和4.x之间的行为发生了变化。在Bash 3.x中,set -- foo;echo“$ {@:0}”仅产生foo,而4.x(至少在4.3.42)产生{value-of-$0} foo。请注意,如果从未调用“set”,则两个版本都不包括“$0”。 - mklement0
谢谢,这正是我要找的!只是为了确保我理解正确,你并没有删除任何参数,而是在说“保留从位置1(即hello)开始到最后一个位置的参数(即there)之间的所有内容”,对吗? - Girrafish
1
不。在技术上,这意味着用从第一个参数开始并持续到倒数第二个参数的参数替换所有参数。因此,它的效果是删除最后一个参数。 - John1024

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接