如何重用和命令apt up
的部分,以便在一行中按顺序执行两个命令,而无需别名。apt update
apt upgrade
就像是:apt up{date,grade}
。
答案1
简单的方法(并且更有效)是通过 for 循环(在一行中,但这里为了清楚起见以多行显示):
for i in {date,grade}; do
apt up${i}
done
聪明的方法是给这两个命令创建一个别名~/.bashrc
,这样就不用再重新输入了:
alias upgrade=' sudo apt update && sudo apt upgrade'
详细的做法是这样的:
$ echo sudo" "apt" "up{"date","grade"}" && " :
sudo apt update && sudo apt upgrade && :
看看发生了什么?我们正在构建一个有效的文本字符串以供 shell 运行。现在您需要做的就是使用eval
而不是echo
。但eval
在 shell 脚本中通常不建议使用 ,并且此命令比 for 循环更复杂且不可移植。主题的变体没有 eval(迄今为止最短,但由于管道和多个命令echo
,两个apt
,sudo
以及sh
大量分叉,效率不高):
$ echo "apt "{update,upgrade}";"|sudo sh
我们还可以使用set
将所需的序列转换为位置参数,然后使用apt
和$1
参数执行$2
:
$ set {update,upgrade}; echo apt $1 && echo apt $2
apt update
apt upgrade
或者再次使用 for 循环,因为如果你没有在中指定序列,它会默认处理位置参数for variable (sequence)
$ set {update,upgrade} ; for i; do echo apt $i ;done
apt update
apt upgrade
使用set
是一种非常常见的技术,我经常在经常使用 shell 的专业人士中看到这种技术,原因很简单 - 这种技术非常便携,可以在/bin/sh
没有数组或{a,b,c}
扩展的情况下工作。因此,POSIX-ly 可移植方式将是set update upgrade ; for i; do echo apt $i ;done
。此外,这应该是高效的。
或者我们可以走while
循环路线:
$ echo {date,$'\n',grade}|while read i;do echo apt up${i}; done
apt update
apt upgrade
当然,请记住,echo
在实际命令执行之前不要运行它
答案2
您也可以使用 bash历史扩展获取当前命令行的部分内容并修改它:
$ apt update; !#:s/date/grade
apt update; apt upgrade;
Reading package lists... Done
...
!#
是当前行:s/date/grade
date
是替代修饰符grade
答案3
另一个简单的选择是使用xargs
而不是for
:
echo up{dat,grad}e | xargs -n1 apt
测试:
$ echo up{dat,grad}e | xargs -n1 echo apt
apt update
apt upgrade
不过,我更喜欢 shell 别名就像 Sergiy 一样因为这些“简单”的方法并不够简单,实际上并不实用。
答案4
@muru 的回答让我读到了历史扩展我发现了另一种变体
$ sudo apt update
$ ^dat^grad^
^string1^string2^
相当于!!:s/string1/string2/
,它采用最后一个命令并替换string1
为string2
。