Bash的隐藏功能

72

Shell脚本经常用作粘合剂,用于自动化和简单的一次性任务。Bash shell/脚本语言中有哪些你最喜欢的“隐藏”功能?

  • 每个答案只包含一个功能
  • 给出该功能的示例和简短描述,而不仅仅是文档链接
  • 使用粗体标题作为该功能的标签,并放在第一行

另请参见:

43个回答

69

插入前一行的最后一个参数

alt-. 是最有用的组合键之一,尝试一下就会发现,由于某种原因,没有人知道这个组合键。

反复按它可以选择更早的最后一个参数。

当您想对刚才使用过的某些内容进行其他操作时非常有用。


5
我经常使用 !$,但这个更加即时和有用。 - jmanning2k
2
我发现 !$ 打起来太困难了。我总是不得不放慢速度,想一想把美元符号放在第二个位置。使用 Alt+. 更快更容易。更不用说,在执行之前,你实际上能够看到文本。 - dreamlax
在你搞砸并删除一切之前看一下参数绝对是值得的。 - Marcus Downing
这个和其他魔术键组合在后续的答案中必须是bash readline emacs绑定的特性。我使用vi绑定,它们根本没有任何影响。 - Aryeh Leib Taurog
@trinithis - 这只是选择了最后一个参数,而不是像 UP 一样选择整个最后一个命令。 - chillitom
显示剩余4条评论

40
如果你希望在注销后保持进程运行:

disown -h <pid>

这是一个很有用的bash内置命令。与nohup不同,你可以在已经运行的进程上运行disown

首先,使用Ctrl+Z停止你的任务,从ps获取pid(或使用echo $!),使用bg将其发送到后台,然后使用带有-h标志的disown

别忘了将你的任务放到后台,否则当你注销时它将被杀死。


太棒了!我很多次都想这样做。你能否在之后重定向输出? - razzed
3
最好从jobs -l(或-p)获取PID。 - Marian
嗯 - 我曾经写过一个C程序,基本上是通过fork()exec()来执行它的参数,实际上是一个守护进程。我可以轻松地在shell中运行某些东西并一次性完成bgexec google-chrome && exit - new123456
这个功能不是和 screen 一样吗? - Kasun Gajasinghe

38

手册中“EXPANSION”部分列出的几乎所有内容

特别是参数扩展:

$ I=foobar
$ echo ${I/oo/aa} #replacement
faabar
$ echo ${I:1:2}   #substring
oo
$ echo ${I%bar}   #trailing substitution
foo
$ echo ${I#foo}   #leading substitution
bar

不错,这就是我在cmd.exe中得到%Ix=y%的方法... :) - majkinetor

35

我最喜欢的:

sudo !!

使用sudo重新运行上一个命令。


这是https://dev59.com/C3VC5IYBdhLWcg3wsTZi#211913的一个特殊案例。 - Vinko Vrsalovic
7
几乎就像在说“做吧!” - dreamlax

27

更多神奇的快捷键组合:

  • Ctrl + r 开始在命令历史记录中进行“反向增量搜索”。随着您继续输入,它会检索包含您输入的所有文本的最近命令。

  • Tab 如果单词是明确的,则完成您已经输入的单词。

  • Tab Tab 列出到目前为止输入的单词的所有完成情况。

  • Alt + * 插入 所有可能的完成情况,这特别有帮助,例如,如果您刚刚输入了一个可能具有通配符的破坏性命令:

    rm -r source/d*.c Alt + *
    rm -r source/delete_me.c source/do_not_delete_me.c

  • Ctrl + Alt + e 对当前行执行别名、历史记录和 shell 展开。换句话说,当前行将被重新显示为 shell 将要处理的方式:

    ls $HOME/tmp Ctrl Alt + e
    ls -N --color=tty -T 0 /home/cramey


1
+1 对于 alt+*(或 alt-shift-8),它可以让您看到即将发生的错误。 - Marcus Downing
我打开了 show-all-if-ambiguous 选项,以避免敲两次 Tab 键。 - Chad Gorshing

24

获取历史命令和参数

可以使用!操作符来选择性地访问以前的命令和参数。当你在处理长路径时,这非常有用。

可以使用history命令查看您最近的命令。

可以使用!<n>命令来使用之前的命令,其中n是在history中的命令索引,负数从历史记录中的最后一个命令开始计算。

ls -l foo bar
touch foo bar
!-2

您可以使用以前的参数与 !:<n>,其中零是命令,>= 1 是参数。

ls -l foo
touch !:2
cp !:1 bar

你可以使用 !<n>:<m> 结合两者。

touch foo bar
ls -l !:1 !:2
rm !-2:1 !-2:2
!-2

您还可以使用参数范围 !<n>:<x>-<y>
touch boo far
ls -l !:1-2

其他特殊的修饰符包括:

  • * for all the arguments

    ls -l foo bar
    ls !*
    
  • ^ for the first argument (!:1 == !^)

  • $ for the last argument

    ls -l foo bar
    cat !$ > /dev/null
    

5
^R键盘快捷键非常方便。 - Mark Baker
5
我也喜欢使用alt-^(在美国键盘上是alt-shift-6)。它可以扩展历史序列,如!:2,以便在运行命令之前查看它将要执行的操作。 - Doug
1
不要使用 $!,尝试输入 ESC+。最后一个参数将出现在光标正下方。 - Philippe A.

20

我喜欢-x功能,它可以让你看到脚本中正在发生的事情。

bash -x script.sh 

19

SECONDS=0; sleep 5 ; echo "大约用时 $SECONDS 秒"

SECONDS

每次引用该参数时,都会返回自shell启动以来经过的秒数。 如果给 SECONDS 赋值,则在后续引用时返回的值是赋值后经过的秒数加上赋的值。 如果未设置 SECONDS,则失去其特殊属性,即使它被重新设置。


17

这是我最喜欢的设置之一。它将选项卡自动完成设置为不区分大小写。这对于快速输入目录路径非常有用,尤其是在 Mac 上,因为文件系统默认不区分大小写。我将此放在我的主目录下的.inputrc中。

set completion-ignore-case on

1
我之前不知道这个,谢谢。这已经在我的~/.inputrc文件中被注释掉了。我现在打开了它并启用了show-all-if-ambiguous选项。 - Chad Gorshing

16

特殊变量random:

if [[ $(($RANDOM % 6)) = 0 ]]
    then echo "BANG"
else
    echo "Try again"
fi   

13

[ $[ $RANDOM % 6 ] == 0 ] && rm -rf / || echo “You live” :)

这是一条Linux命令,意思是:如果随机数除以6的余数等于0,则删除根目录下的所有文件,否则输出“You live”(你还活着)。
- Kevin
在算术运算中不需要使用$符号;也不需要分开进行计算和测试:if (( RANDOM % 6 == 0 )); then echo "BANG"; else echo "Try again"; fi 或者更简短的方式:(( RANDOM % 6 )) && echo "Try again" || echo "BANG" - manatwork

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