Shell脚本通常用作粘合剂,用于自动化和简单的一次性任务。您最喜欢的Bash shell /脚本语言的“隐藏”功能是什么?
另见:
答案 0 :(得分:69)
插入前一行的最终参数
alt - 。有史以来最有用的组合键,尝试看看,由于某些原因,没有人知道这个。
反复按此按钮选择较旧的最后一个参数。
当你想要对你刚才使用过的东西做其他事情时,这很棒。
答案 1 :(得分:40)
如果您希望在注销后继续运行流程:
disown -h <pid>
是一个有用的bash内置。与nohup
不同,您可以在已经运行的流程上运行disown
。
首先,使用control-Z停止工作,从ps
获取pid(或使用echo $!
),使用bg
将其发送到后台,然后使用{{1带-h标志。
不要忘记记录你的工作,否则当你退出时就会被杀死。
答案 2 :(得分: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
答案 3 :(得分:35)
我的最爱:
sudo !!
使用sudo重新运行上一个命令。
答案 4 :(得分:27)
Ctrl + r 通过命令历史记录开始“反向增量搜索”。当您继续键入时,它会检索包含您输入的所有文本的最新命令。
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
答案 5 :(得分:24)
取回历史记录命令和参数
可以使用!
运算符有选择地访问以前的命令和参数。当您使用长路径时,它非常有用。
您可以使用history
检查上一个命令。
您可以使用!<n>
n
之前的命令history
ls -l foo bar
touch foo bar
!-2
中的命令索引,负数从历史记录中的最后一个命令向后计数。
!:<n>
您可以将以前的参数与ls -l foo
touch !:2
cp !:1 bar
一起使用,零是命令,&gt; = 1是参数。
!<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
!
其他*
特殊修饰符为:
ls -l foo bar
ls !*
^
!:1
第一个参数(!^
== $
)
ls -l foo bar
cat !$ > /dev/null
获取最后一个参数
{{1}}
答案 6 :(得分:20)
我喜欢-x功能,允许查看脚本中发生了什么。
bash -x script.sh
答案 7 :(得分:19)
SECONDS=0; sleep 5 ; echo "that took approximately $SECONDS seconds"
<强>秒强>
每次参数都是 引用,秒数 因为返回了shell调用。 如果为SECONDS分配了值, 随后返回的值 references是秒数 因为赋值加上了值 分配。如果没有设置SECONDS,那就是 失去其特殊属性,即使 它随后被重置。
答案 8 :(得分:17)
这是我的最爱之一。这将选项卡完成设置为不区分大小写。这对于快速键入目录路径非常有用,尤其是在默认情况下文件系统不区分大小写的Mac上。我把它放在.inputrc
的主文件夹中。
set completion-ignore-case on
答案 9 :(得分:16)
特殊变量random:
if [[ $(($RANDOM % 6)) = 0 ]]
then echo "BANG"
else
echo "Try again"
fi
答案 10 :(得分:13)
正则表达式处理
最近的bash版本具有正则表达式匹配功能,因此您可以执行以下操作:
if [[ "mystring" =~ REGEX ]] ; then
echo match
fi
其中REGEX是man re_format描述的格式的原始正则表达式。
任何括号内部分的匹配都存储在BASH_REMATCH数组中,从元素1开始(元素0是完整匹配的字符串),因此您也可以使用它来进行正则表达式解析。
答案 11 :(得分:13)
Ctrl x Ctrl e
这会将当前命令加载到变量VISUAL中定义的编辑器中。这对于像这里列出的一些长命令非常有用。
使用vi作为编辑器:
export VISUAL=vi
答案 12 :(得分:13)
快速&amp;拼写错误的纠正(对于使用命令历史记录并滚动浏览它的慢速连接的长命令尤其有用):
$ cat /proc/cupinfo
cat: /proc/cupinfo: No such file or directory
$ ^cup^cpu
同时尝试使用上一个命令中的old替换old !:s/old/new
一次。
如果要替换多次出现,可以使用!:gs/old/new
进行全局替换。
您可以将gs
和s
命令用于任何历史事件,例如
!-2:s/old/new
在倒数第二个命令中用old
替换new
(一次)。
答案 13 :(得分:10)
这是我最喜欢的两个:
要检查没有真正执行脚本的语法,请使用:
bash -n script.sh
回到最后一个目录(是的,我知道pushd和popd,但这更快)
cd -
答案 14 :(得分: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
对于下一个4月的傻瓜,将“export PROMPT_COMMAND = cd”添加到某人的.bashrc然后坐下来观看混乱的展开。
答案 15 :(得分: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
有关数组(以及其他高级bash脚本编写内容)的更多详细信息,请参见Advanced Bash-Scripting Guide。
答案 16 :(得分:8)
man
页面的魔术键组合:Ctrl + a 和 Ctrl + e 将光标移动到开头和结尾当前行分别为。
Ctrl + t 和 Alt + t 转置光标前的字符和单词当前的那个,然后向前移动光标。
Alt + u 和 Alt + l 转换当前单词(从光标到结束)大写和小写。
提示:按 Alt + - 后跟其中任何一个命令转换当前的开头字。
man
提示:在查看man
页面时,使用 / 搜索页面中的文本。使用 n 跳转到下一场比赛,或使用 N 进行上一场比赛。
利用其格式加快搜索man
页面中的特定命令或子部分:
o而不是键入 / history expansion 来查找该部分,尝试 / ^ history ,使用插入符号(^
)仅查找< em>开始与“历史。”
o尝试使用一些前导空格的 / read 来搜索该内置命令。 Builtins总是在man
页面中缩进。
答案 17 :(得分:8)
使用中缀布尔运算符
考虑简单的if:
if [ 2 -lt 3 ]
then echo "Numbers are still good!"
fi
那看起来有点难看。不是很现代。如果在布尔表达式周围使用双括号,则可以使用普通的布尔运算符!
if [[ 2 < 3 ]]
then echo "Numbers are still good!"
fi
答案 18 :(得分:7)
export TMOUT=$((15*60))
空闲时间15分钟后终止bash,设置为0表示禁用。我通常把它放在我的root帐户上的〜/ .bashrc中。管理你的盒子很方便,你可能会忘记在离开终端之前退出。
答案 19 :(得分:7)
C-S - 控制班次减号撤消键入操作。
任何删除操作 Cw (删除前一个单词), Ck (删除到行尾), Cu (删除到行开头) )等...将其删除的文本复制到kill ring,你可以粘贴最后一个kill: Cy 并使用 Alt-y循环(并粘贴)已删除项目的环
答案 20 :(得分:7)
通过设置FIGNORE
变量,您可以在标签完成时忽略某些文件。
例如,如果您有一个subverion repo并且想要更轻松地导航
export FIGNORE=".svn"
现在您可以cd
而不被.svn
目录阻止。
答案 21 :(得分:5)
使用算术:
if [[ $((2+1)) = $((1+2)) ]]
then echo "still ok"
fi
答案 22 :(得分:5)
支持扩张
{x,y,z}的标准扩展:
$ echo foo{bar,baz,blam}
foobar foobaz fooblam
$ cp program.py{,.bak} # very useful with cp and mv
使用{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
答案 23 :(得分:4)
截断文件内容(归零文件)
> file
具体来说,这对于截断日志文件非常有用,当文件被另一个进程打开时,该进程仍然可以写入该文件。
答案 24 :(得分:4)
在for循环中代替do
和done
的大括号
For
循环体通常在do...done
中(仅作为示例):
for f in *;
do
ls "$f";
done
但我们可以使用大括号的C风格:
for f in *; {
ls "$f";
}
我认为这看起来比do...done
更好,我更喜欢这个。我还没有在任何Bash文档中找到它,所以这真的是一个隐藏的功能。
答案 25 :(得分:4)
我最近阅读了包含这个令人震惊的宝石的Csh Programming Considered Harmful:
考虑管道:
A | B | C
你想知道C的状态,那很容易:它在$?中,或者 csh中的$ status。但如果你想从A那里得到它,那你就不幸了 - 如果 你在csh,就是这样。但是在Bourne shell中,你可以得到它 这样做有点棘手。 这是我在运行dd时必须做的事情 stderr进入grep -v管道以摆脱记录输入/输出噪声,但已经 返回dd的退出状态,而不是grep的:
device=/dev/rmt8
dd_noise='^[0-9]+\+[0-9]+ records (in|out)$'
exec 3>&1
status=`((dd if=$device ibs=64k 2>&1 1>&3 3>&- 4>&-; echo $? >&4) |
egrep -v "$dd_noise" 1>&2 3>&- 4>&-) 4>&1`
exit $status;
答案 26 :(得分:4)
另一个小小的: 替代 + #
注释掉当前行并将其移入历史缓冲区。
因此,在组装命令行时,需要发出临时命令,例如找到一个文件,你只需按下alt +#,发出另一个命令,在历史记录中查找,取消注释并继续。
答案 27 :(得分:4)
不是一个功能而是一个方向:我在commandlinefu.com找到了许多“隐藏的功能”,秘密和各种bash实用性。许多评价最高的答案,我在那个网站上学到了它们:)
答案 28 :(得分:3)
set -o vi
,以便对命令历史记录以及当前键入的命令进行类似vi的编辑。
答案 29 :(得分:3)
轻松在多个目录之间移动
不是隐藏功能,但比pushd更灵活,需要类似堆栈的导航。
a() { alias $1=cd\ $PWD; }
cd
某处并输入a 1
。稍后只需输入1
即可返回该目录。
答案 30 :(得分:3)
C风格的数字表达式:
let x="RANDOM%2**8"
echo -n "$x = 0b"
for ((i=8; i>=0; i--)); do
let n="2**i"
if (( (x&n) == n )); then echo -n "1"
else echo -n "0"
fi
done
echo ""
答案 31 :(得分:3)
这些属性是我的另一个属性。
export HISTCONTROL=erasedups
export HISTSIZE=1000
第一个确保bash不会多次记录命令,真的会提高history
的实用性。另一个将历史记录大小从默认值100扩展到1000.我实际上在我的机器上将其设置为10000。
答案 32 :(得分:3)
我经常使用的是!$来引用最后一个命令的最后一个字:
$ less foobar.txt
...
# I dont want that file any more
$ rm !$
答案 33 :(得分:2)
Bash有变量间接:
$ foo=bar
$ baz=foo
$ echo ${!baz}
bar
答案 34 :(得分:2)
我有一个别名r='fc-s'
,我发现它在某些有限的情况下非常有用。要运行最后一个命令,只需键入r
并按Enter键即可。当然,这本身并不是很有用,因为向上箭头做同样的事情。但您可以使用r
运行带有替换的上一个命令。假设您的最后一个命令是编译某个文件的长命令:
$ gcc -c <file_name>.c <lots of options> -o <file_name>.o
现在您要编译具有相同选项的另一个文件并具有相应的.o
文件:
$ r <file_name>=<new_file>
会做到的。您不必使用向上箭头,导航到正确的位置,然后手动替换它们。这可以重复多次,因此您可以执行以下操作:
$ r <new_file>=<other_file>
当然,对于这样的事情,你有makefile,但我希望我已经证明别名是有用的。
我不需要使用这个别名,但有时候我很高兴我有这个别名!
答案 35 :(得分:2)
正如其他人所提到的, Ctrl - r 非常适合退回命令历史记录。但是,如果你想要在经过一个或几个步骤之后继续前进怎么办?这就是 Ctrl - s 派上用场的地方。但是,它通常映射到XOFF(中断数据流)。由于我们不使用慢速串行终端,因为它不再有用,你可以用以下方式关闭该映射:
stty -ixon
在~/.bashrc
文件中。
这也使 Ctrl - q 可用,这通常是 Ctrl - v 的重复(引用 - 插入,允许您插入文字控制字符)。我有 Ctrl - q 映射到menu-complete,当重复按下时会逐步完成完成。我想将 Tab 设置为常规完成。
您可以通过将此行添加到~/.inputrc
文件来将 Ctrl - q 设置为菜单完成:
"\C-q": menu-complete
答案 36 :(得分:2)
此处字符串(<<<
)。 Bash手册给出了这样的描述:
单词被扩展并在其标准输入上提供给命令。
示例:
$ cat<<<"$(( 10*3+1 )) nice isn't it?"
31 nice isn't it?
答案 37 :(得分:1)
使用'let'内置bash命令进行基本算术
A=10
let B="A * 10 + 1" # B=101
let B="B / 8" # B=12, let does not do floating point
let B="(RANDOM % 6) + 1" # B is now a random number between 1 and 6
要进行浮点计算,可以使用“bc”命令(不是bash的一部分)。
FP=`echo "scale=4; 10 / 3" | bc` # FP="3.3333"
答案 38 :(得分:1)
使用&lt;(cmd ...)或&gt;(cmd ...)
进行替换在每种形式中,执行cmd时,其输入或输出连接到FIFO,并且在命令行上替换该FIFO的路径:
$ echo A file to read: <(cat), a file to write to: >(cat)
A file to read: /dev/fd/63, a file to write to: /dev/fd/62
例如,比较两个网站而不保存中间文件:
$ diff <(curl -s http://tldp.org/LDP/abs/html/) <(curl -s http://www.redhat.com/mirrors/LDP/LDP/abs/html/)
如果你有一个命令将文件名作为输入,但不接受' - '表示stdout,你可以欺骗它:
$ do_thingee --log -
error: can't open log file: '-'
$ do_thingee --log >(cat)
do_thingee v0.2
initializing things
processing 4 things
done
答案 39 :(得分:1)
特殊套接字文件名:/ dev / tcp / HOST / PORT和/ dev / udp / HOST / PORT
从日间服务器(端口13)读取:
$ cat < /dev/tcp/utcnist.colorado.edu/13
55786 11-08-13 03:34:21 50 0 0 172.3 UTC(NIST) *
这与tcpserver结合使用非常有用。
如果您无权访问wget或curl,则来自http://thesmithfam.org/blog/2006/05/23/bash-socket-programming-with-devtcp-2/的更高级示例:
$ exec 3<>/dev/tcp/www.google.com/80 # hook up to file desc 3
$ echo -e "GET / HTTP/1.1\n\n" >&3 # send the HTTP request
$ cat <&3 # read the HTTP response
答案 40 :(得分:0)
嵌入式命令替换:
主机名&amp;&amp;挖+短$(主机名)&amp;&amp; dig + short -x $(挖掘+短期$(主机名))
此命令适用于检查邮件服务器上的RDNS。 :P
答案 41 :(得分:0)
快速搜索历史记录
以下提供类似历史搜索的tcsh,方便易用。
将以下行添加到~/.inputrc
或/etc/inputrc
。
$ cat ~/.inputrc
"\e[A": history-search-backward
"\e[B": history-search-forward
您可能希望使用意外较少的组合键,例如Esc
+ p
。如果是这种情况,请使用
"\ep": history-search-backward
"\en": history-search-forward
然后,只需键入前几个字母,然后按UpArrow键。它将显示以给定字母开头的最新命令。
例如:
输入grep
,UpArrow。
它会显示grep -ri myText .
答案 42 :(得分:0)
在http://linuxconfig.net/manual-howto/key-combinations-in-bash.html
中获取有关Bash中键组合的更多信息