Bash的隐藏功能

Pat*_*ick 72 bash shell scripting hidden-features

Shell脚本通常用作粘合剂,用于自动化和简单的一次性任务.您最喜欢的Bash shell /脚本语言的"隐藏"功能有哪些?

  • 每个答案一个功能
  • 举一个示例和该功能的简短描述,而不仅仅是文档的链接
  • 使用粗体标题作为第一行标记要素

也可以看看:

chi*_*tom 69

插入前一行的最终参数

alt- . 有史以来最有用的组合键,试试看,由于某种原因,没有人知道这个.

再次按此按钮选择较旧的最后一个参数.

很棒的时候你想对你刚刚用过的东西做些什么.

  • 我经常使用!$,但这更直接和有用. (5认同)
  • 我发现`!$'很难快速打字.我总是要放慢脚步,考虑把美元符号放在第二位.`Alt` +`.`更快更容易.更不用说,在执行之前,您实际上可以看到文本. (2认同)

Ale*_*lds 40

如果要在注销后继续运行进程:

disown -h <pid>

是一个有用的bash内置.与之不同nohup,您可以disown在已经运行的进程上运行.

首先,使用control-Z停止工作,从ps(或使用echo $!)获取pid ,使用bg将其发送到后台,然后使用disown-h标志.

不要忘记背景你的工作,否则当你注销时它会被杀死.

  • 最好从`jobs -l`(或`-p`)获取PID (3认同)

Vin*_*vic 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
Run Code Online (Sandbox Code Playgroud)


Glo*_*ish 35

我的最爱:

sudo !!
Run Code Online (Sandbox Code Playgroud)

用sudo重新运行上一个命令.

  • 这几乎就像说**做它!!** (7认同)

Ada*_*iss 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


Jai*_*ano 24

获取历史命令和参数

可以使用!运算符有选择地访问先前的命令和参数.当您使用长路径时,它非常有用.

您可以查看上一个命令history.

您可以使用以前的命令!<n>作为命令n的索引history,负数从历史记录中的最后一个命令向后计数.

ls -l foo bar
touch foo bar
!-2
Run Code Online (Sandbox Code Playgroud)

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

ls -l foo
touch !:2
cp !:1 bar
Run Code Online (Sandbox Code Playgroud)

你可以将两者结合起来 !<n>:<m>

touch foo bar
ls -l !:1 !:2
rm !-2:1 !-2:2
!-2
Run Code Online (Sandbox Code Playgroud)

您还可以使用参数范围 !<n>:<x>-<y>

touch boo far
ls -l !:1-2
Run Code Online (Sandbox Code Playgroud)

其他!特殊修饰符是:

  • ^ R键盘快捷键也非常方便 (5认同)
  • 我也喜欢alt- ^(美国键盘上的alt-shift-6).它扩展了历史序列,如!:2,因此您可以在运行命令之前查看命令将要执行的操作. (5认同)

ste*_*nea 20

我喜欢-x功能,允许查看脚本中发生了什么.

bash -x script.sh 
Run Code Online (Sandbox Code Playgroud)


Alb*_*gni 19

SECONDS=0; sleep 5 ; echo "that took approximately $SECONDS seconds"

SECONDS

每次引用此参数时,都会返回自返回shell调用以来的秒数.如果为SECONDS分配了值,则后续引用时返回的值是分配后的秒数加上分配的值.如果未设置SECONDS,即使它随后被重置,它也会丢失其特殊属性.


dan*_*nez 17

这是我的最爱之一.这将选项卡完成设置为不区分大小写.这对于快速键入目录路径非常有用,尤其是在默认情况下文件系统不区分大小写的Mac上.我把它放在.inputrc我的主文件夹中.

set completion-ignore-case on
Run Code Online (Sandbox Code Playgroud)


Vin*_*vic 16

特殊变量随机:

if [[ $(($RANDOM % 6)) = 0 ]]
    then echo "BANG"
else
    echo "Try again"
fi   
Run Code Online (Sandbox Code Playgroud)

  • #[$ [$ RANDOM%6] == 0] && rm -rf/|| 回声"你活着":) (13认同)
  • 啊,是的,Баш轮盘赌. (5认同)

th_*_*_gs 13

正则表达式处理

最近的bash版本具有正则表达式匹配功能,因此您可以:

if [[ "mystring" =~ REGEX ]] ; then  
    echo match
fi
Run Code Online (Sandbox Code Playgroud)

其中REGEX是man re_format描述的格式的原始正则表达式.

来自任何括号部分的匹配存储在BASH_REMATCH数组中,从元素1开始(元素0是完整匹配的字符串),因此您也可以使用它来执行正则表达式的解析.


mih*_*ihi 13

拼写错误的快速和肮脏纠正(对于使用命令历史记录并滚动浏览它的慢速连接的长命令尤其有用):

$ cat /proc/cupinfo
cat: /proc/cupinfo: No such file or directory
$ ^cup^cpu
Run Code Online (Sandbox Code Playgroud)

还可以尝试!:s/old/new使用上一个命令中的new替换旧的一次.

如果要替换多次出现,可以使用!:gs/old/new.

您可以将gsand s命令与任何历史事件一起使用,例如

!-2:s/old/new
Run Code Online (Sandbox Code Playgroud)

在倒数第二个命令old中用new(一次)替换.

  • "man bash"中的事件指示符和修饰符.尝试`!:s/old/new`,用上一个命令中的old代替old.如果要替换多次出现,可以使用`!:gs/old/new`进行全局替换.这可能与詹姆斯的帖子(http://stackoverflow.com/questions/211378/hidden-features-of-bash/211913#211913)相结合,例如:`!$:s/old/new`(替换旧的在上一个命令的最后一个参数中是新的,`! - 2:0:gs/a/s!-2*`(用倒数第二个命令名中每次出现的s替换,并添加倒数第二个命令的所有参数).祝好运! (3认同)

Rob*_*bin 13

Ctrlx Ctrle

这会将当前命令加载到变量VISUAL中定义的编辑器中.这对于像这里列出的一些长命令非常有用.

要使用vi作为编辑器:

export VISUAL=vi
Run Code Online (Sandbox Code Playgroud)

  • 哇.很有用! (2认同)

And*_*dré 10

这是我最喜欢的两个:

要检查没有真正执行脚本的语法,请使用:

bash -n script.sh
Run Code Online (Sandbox Code Playgroud)

回到最后一个目录(是的,我知道pushd和popd,但这更快)

cd -
Run Code Online (Sandbox Code Playgroud)

  • "cd - "具有工作的优势,如果您忘记将目录推入堆栈但仍想返回那里. (3认同)

Pat*_*ick 8

使用中缀布尔运算符

考虑简单的if:

if [ 2 -lt 3 ]
    then echo "Numbers are still good!"
fi
Run Code Online (Sandbox Code Playgroud)

那看起来有点难看.不是很现代.如果在布尔表达式周围使用双括号,则可以使用普通的布尔运算符!

if [[ 2 < 3 ]]
    then echo "Numbers are still good!"
fi
Run Code Online (Sandbox Code Playgroud)

  • 不,'['是一个独立的计划.'[[' 不是 (5认同)
  • 这不是Bash的功能,而是外部程序:是的,'[['是一个独立的程序. (3认同)
  • madmath:我想你会发现[通常是一个符号链接或硬链接来测试,而[[是一个内置的shell].它需要由shell解析,否则<看起来像输入重定向. (2认同)

Jes*_*erE 8

阵列:

#!/bin/bash

array[0]="a string"
array[1]="a string with spaces and \"quotation\" marks in it"
array[2]="a string with spaces, \"quotation marks\" and (parenthesis) in it"

echo "There are ${#array[*]} elements in the array."
for n in "${array[@]}"; do
    echo "element = >>${n}<<"
done
Run Code Online (Sandbox Code Playgroud)

有关数组(以及其他高级bash脚本编写内容)的更多详细信息,请参阅Advanced Bash-Scripting Guide.


Sha*_*hin 8

在显示bash提示符之前运行命令

在"PROMPT_COMMAND"env变量中设置一个命令,它将在每个提示之前自动运行.例:

[lsc@home]$ export PROMPT_COMMAND="date"
Fri Jun  5 15:19:18 BST 2009
[lsc@home]$ ls
file_a  file_b  file_c
Fri Jun  5 15:19:19 BST 2009
[lsc@home]$ ls
Run Code Online (Sandbox Code Playgroud)

对于下一个愚人节,将"export PROMPT_COMMAND = cd"添加到某人的.bashrc,然后坐下来看着混乱展开.


Ada*_*iss 8

来自bash man页面的魔术组合键:

  • Ctrl+ aCtrl+分别e将光标移动到当前行的开头和结尾.

  • Ctrl+ tAlt+ t将光标前的字符和单词转换为当前的字符和单词,然后向前移动光标.

  • Alt+ uAlt+ l将当前单词(从光标到结尾)转换为大写和小写.

    提示:Alt+ 后跟这些命令中的任何一个来转换当前单词的开头.


额外man提示:

  • 查看man页面时,用于/搜索页面中的文本.使用n提前跳转到下一场比赛或N前一个比赛.

  • man通过利用其格式来加速搜索页面中的特定命令或子部分:

    o /history expansion尝试/^history使用插入符号(^)仅查找以"历史记录" 开头的行,而不是键入以查找该节.

    o尝试/   read使用一些前导空格来搜索内置命令.Builtins总是在man页面中缩进.


aDe*_*Dev 7

export TMOUT=$((15*60))

空闲时间15分钟后终止bash,设置为0表示禁用.我通常把它放在我的root帐户上的〜/ .bashrc中.管理您的盒子时很方便,您可能会在离开终端之前忘记注销.


oco*_*odo 7

解开

C-S-- 控制Shift减去撤消键入操作.

杀/ Yank

任何删除操作C-w(删除前一个单词),C-k(删除到行尾),C-u(删除到行尾)等...将其删除的文本复制到kill ring,你可以粘贴最后一个kill:C-y并循环通过(和粘贴来自已删除项目的环Alt-y


Sio*_*e21 7

通过设置FIGNORE变量,可以在制表符完成时忽略某些文件.

例如,如果您有一个subverion repo,并且您想要更轻松地导航

export FIGNORE=".svn"
Run Code Online (Sandbox Code Playgroud)

现在你可以cd不被.svn目录阻止.


Vin*_*vic 5

使用算术:

if [[ $((2+1)) = $((1+2)) ]]
    then echo "still ok"
fi
Run Code Online (Sandbox Code Playgroud)

  • 有时算术扩展就足够了:((2 + 1 == 1 + 2))&& echo OK (2认同)

Tom*_*Tom 5

支撑扩张

使用{x,y,z}进行标准扩展:

$ echo foo{bar,baz,blam}
foobar foobaz fooblam
$ cp program.py{,.bak}  # very useful with cp and mv
Run Code Online (Sandbox Code Playgroud)

使用{x..y}进行序列扩展:

$ echo {a..z}
a b c d e f g h i j k l m n o p q r s t u v w x y z
$ echo {a..f}{0..3}
a0 a1 a2 a3 b0 b1 b2 b3 c0 c1 c2 c3 d0 d1 d2 d3 e0 e1 e2 e3 f0 f1 f2 f3
Run Code Online (Sandbox Code Playgroud)