有关bash,我希望我能知晓的十件事
简介
我之前的一篇文章比我预想的更受欢迎,因此我想再写一篇文章来介绍一些不太知名的bash功能
正如之前所言,由于我觉得bash是一种要经常使用(且需理解)的技术,所以我在研究bash时写了一本书。虽然许多人并不熟悉bash,但我觉得他们也认为非常重要便足够令人欣喜。
1)^x^y^
我总在使用的一个小技巧。
从来没有输入过类似的命令?
$ grp somestring somefile
-bash: grp: command not found
哎,这个命令敲错了,所以你要敲“↑”,然后敲”←“直到”p“,然后输入”e"再执行。
或者这样输入:
$ ^rp^rep^
grep 'somestring' somefile
$
你可能需要注意的一个细节是:
$ grp rp somefile
$ ^rp^rep^
$ grep rp somefile
如果你想搜索“rep”,那你就要深入研究man page,学会使用这个更强大的命令:
$ grp rp somefile
$ !!:gs/rp/rep
grep rep somefile
$
我不会在这里解释这个用法。。。
2)pushd/popd
这个在脚本中非常好用,特别是在循环中
如下所示,假设你正在写一个进入退出文件夹的for循环:
for d1 in $(ls -d */)
do
# Store original working directory.
original_wd="$(pwd)"
cd "$d1"
for d2 in $(ls -d */)
do
pushd "$d2"
# Do something
popd
done
# Return to original working directory
cd "${original_wd}"
done
你可以像这样使用pushd栈来重写上方代码:
for d1 in $(ls -d *)
do
pushd "$d1"
for d2 in $(ls -d */)
do
pushd "$d2"
# Do something
popd
done
popd
done
它可以追踪记录你切换的目录并进行入栈或出栈
注意,当使用pushd出现错误时,可能会丢失栈的记录并且popd多次。因此你可能会想要在脚本中使用set -e(见上一篇文章)
当然也可以用cd -,但是它不会使用栈——仅仅返回前一个目录
cd ~
cd /tmp
cd blah
cd - # Back to /tmp
cd - # Back to 'blah'
cd - # Back to /tmp
cd - # Back to 'blah' ...
3) shopt vs set
这两个命令困扰了我一阵子。
两者之间有什么不同呢?
set在之前的文章已经介绍过了,而shopt看起来与之相似。只输入shopt会显示一系列选项:
$ shopt
cdable_vars off
cdspell on
checkhash off
checkwinsize on
cmdhist on
compat31 off
dotglob off
我在这里( here)找到了一些答案。
从根本上说,似乎有一系列的bash(和其他shells)建立在sh之上,而添加shopt命令则为设置额外的shell选项提供了一种方式
但是我也不确定……如果你知道为什么,请告诉我。
4)Here Docs 与 Here Strings
“Here Docs”是在shell中用一些语句创建的文件。
“诀窍”很简单。定义一个用于结束的单词,则在这个单词单独出现在一行之前的所有输入行将构成文件。
像这样:
$ cat > afile << SOMEENDSTRING
> here is a doc
> it has three lines
> SOMEENDSTRING alone on a line will save the doc
> SOMEENDSTRING
$ cat afile
here is a doc
it has three lines
SOMEENDSTRING alone on a line will save the doc
$
注意:
· 如果结束单词不是“单独”出现在一行中,那它可以构成文件
· SOMEENDSTRING通常是END,但这仅仅只是习惯
更鲜为人知的是“here string”:
$ cat > asd <<< 'This file has one line'
5)字符串变量的操作
以前你可能是像下面展示的那样写代码,用sed一类的工具来操作字符串:
$ VAR='HEADERMy voice is my passwordFOOTER'
$ PASS="$(echo $VAR | sed 's/^HEADER(.*)FOOTER/1/')"
$ echo $PASS
但是你可能不知道bash本身也是可以的。
这意味着你可以省去大量的sed和awk。
一种重写上述代码的方式如下所示:
$ VAR='HEADERMy voice is my passwordFOOTER'
$ PASS="${VAR#HEADER}"
$ PASS="${PASS%FOOTER}"
$ echo $PASS
·#表示“从字符串开头开始匹配并删除所给的模式串”
·%表示“从字符串结尾开始匹配并删除所给的模式串”
在我的电脑上,后一种方法比前一种快两倍。并且(令我吃惊的是),他的速度跟类似功能的python脚本速度大致相当
如果你想使用通配符(见前文)模式串并采用贪婪模式,你需要双写:
$ VAR='HEADERMy voice is my passwordFOOTER'
$ echo ${VAR##HEADER*} $ echo ${VAR%%*FOOTER}
6)变量的默认值
这些对写脚本来说非常好用。
如果你有一个没有赋值的变量,你可以像这样给它“赋默认值”
创建一个default.sh文件,写入如下内容:
#!/bin/bash
FIRST_ARG="${1:-no_first_arg}"
SECOND_ARG="${2:-no_second_arg}"
THIRD_ARG="${3:-no_third_arg}"
echo ${FIRST_ARG}
echo ${SECOND_ARG}
echo ${THIRD_ARG}
现在执行chmod +x default.sh并用./default.sh first second来运行脚本:
观察第三个参数的默认值是如何被分配的,而不是前两个。
你也可以直接用${VAR:=defaultval}(等号,不是破折号),但是注意这不适用于脚本或函数中的位置变量。尝试修改上面的脚本来看它是如何失败的。
7)Traps
当一个信号被送到脚本时,内建的trap可以用于“捕获”
下面是我用在自己的chepci脚本中的一个例子:
function cleanup() {
rm -rf "${BUILD_DIR}"
rm -f "${LOCK_FILE}"
# get rid of /tmp detritus, leaving anything accessed 2 days ago+
find "${BUILD_DIR_BASE}"/* -type d -atime +1 | rm -rf
echo "cleanup done"
}
trap cleanup TERM INT QUIT
任何使用TERM信号的CTRL-C,CTRL-或终止程序的操作将会首先调用cleanup
注意:
·trap的逻辑可能非常棘手(例如处理信号竞争条件)
·KILL信号不能以这种方式捕获
但是大多数情况下,我会把它用于类似上述的‘cleanup’中,来达成函数的目的。
8)Shell变量
了解可用的标准shell变量是非常值得的。这些是我最喜欢的。
RANDOM
不要依赖这个来加密堆栈,但你可以生成随机数字,例如在脚本中创建临时文件时:
$ echo ${RANDOM}
16313
$ # Not enough digits?
$ echo ${RANDOM}${RANDOM}
113610703
$ NEWFILE=/tmp/newfile_${RANDOM}
$ touch $NEWFILE
REPLY
不在需要给read一个变量名称
$ read
my input
$ echo ${REPLY}
LINENO 与 SECONDS
方便调试
$ echo ${LINENO}
115
$ echo ${SECONDS}; sleep 1; echo ${SECONDS}; echo $LINENO
174380
174381
116
注意,即便使用;来隔开命令,上面的代码也要分两行
TMOUT
可以用来超时读取,在一些脚本中真的很好用
#!/bin/bash
TMOUT=5
echo You have 5 seconds to respond...
read
echo ${REPLY:-noreply}
9) Extglobs
如果你真的沉迷bash不能自拔,那么你可能想要增强你的通配功能。你可以通过设置shell中的extglob选项。这是设置方法:
shopt -s extglob
A="12345678901234567890"
B=" ${A} "
现在来看看你是否能指出以下这些语句各自的功能:
echo "B |${B}|"
echo "B#+( ) |${B#+( )}|"
echo "B#?( ) |${B#?( )}|"
echo "B#*( ) |${B#*( )}|"
echo "B##+( )|${B##+( )}|"
echo "B##*( )|${B##*( )}|"
echo "B##?( )|${B##?( )}|"
虽然它可能很有用,但是很难想象出一种你必须要用这种方式的情况。通常你会使用一些更适合相应任务的工具(像sed)或者直接放弃bash去使用一些像python那样的“合适的”编程语言。
10)关联数组
谈到移植到其他语言,一条重要的规则是,如果我需要用到数组,那么我会放弃bash,使用python(为此我甚至创建了一个Docker Container来运行一个专门的工具)
知道读到它我才知道,在bash中有关联数组
以下是演示:
$ declare -A MYAA=([one]=1 [two]=2 [three]=3)
$ MYAA[one]="1"
$ MYAA[two]="2"
$ echo $MYAA
$ echo ${MYAA[one]}
$ MYAA[one]="1"
$ WANT=two
$ echo ${MYAA[$WANT]}
注意仅适用于bash4.x+版本
看完以上的内容,相信你对于Linux运维的了解又加深了一层。作为一名Linux爱好者,如果你在学习中遇到了困惑需要交流,可以来我们的网站(http://www.magedu.com/)获取帮助,了解行业评价最高的Linux课程可以拨打电话:18519746220。
有关bash,我希望我能知晓的十件事的更多相关文章
- 我希望知道的关于Django的11件事(转)
英文原文:https://medium.com/cs-math/f29f6080c131 译文:http://my.oschina.net/chenlei123/blog/270672 两年前, 我开 ...
- 4 Things I Wish I Would Have Known When I Started My Software Development Career【当我最开始从事软件工程师的时候我希望我知道的四件事】
英文原文:http://simpleprogrammer.com/2013/08/19/software-development-career/ My software development car ...
- 如果做好测试PM【转载】
本文来源于:https://yq.aliyun.com/articles/14578?spm=5176.100238.yqhn2.14.Lcie4Y 摘要今年整体带了几个项目.我本人不是专业的PM ...
- 数字IC设计工程师的知识结构
刚毕业的时候,我年少轻狂,以为自己已经可以独当一面,庙堂之上所学已经足以应付业界需要.然而在后来的工作过程中,我认识了很多牛人,也从他们身上学到了很多,从中总结了一个IC设计工程师需要具备的知识架构, ...
- GCD的深入理解
GCD 深入理解(一) 本文由@nixzhu翻译至raywenderlich的<grand-central-dispatch-in-depth-part-1> 虽然 GCD 已经出现过一段 ...
- GCD 深入理解:第二部分
在本系列的第一部分中,你已经学到超过你想像的关于并发.线程以及GCD 如何工作的知识.通过在初始化时利用 dispatch_once,你创建了一个线程安全的 PhotoManager 单例,而且你通过 ...
- 2817 Tangent的愤怒 - Wikioi
题目描述 Description 如果机房马上要关门了,或者你急着要和MM约会,请直接跳到第六个自然段. 第二段:本题改编自Usaco Training 4.4.2... 第三段:本题加大了数据强度. ...
- 转:十条不错的编程观点。(出处:酷 壳 – CoolShell.cn)
在Stack Overflow上有这样的一个贴子<What’s your most controversial programming opinion?>,翻译成中文就是“你认为最有争议的 ...
- GCD 深入理解
GCD 深入理解(一) 虽然 GCD 已经出现过一段时间了,但不是每个人都明了其主要内容.这是可以理解的:并发一直很棘手,而 GCD 是基于 C 的 API ,它们就像一组尖锐的棱角戳进 Object ...
随机推荐
- 单点登录之CAS简介
cas官网http://www.ja-sig.org/products/cas/. ok,如今開始本文的重点内容解说,先来了解一下cas 实现single sign out的原理,如图所看到的: ...
- ios18---自定义控件3改进
控制器: // XMGViewController.h #import <UIKit/UIKit.h> @interface XMGViewController : UIViewContr ...
- 【Codeforces】Round #376 (Div. 2)
http://codeforces.com/contest/731 不发题面了,自己点链接 总结一下 考场上 原以为这次要加很多raiting... 但FST狗记邓,只加了58rating 总结一下 ...
- Python: PS 滤镜--马赛克
本文利用 Python 实现PS 滤镜中的马赛克效果,具体的算法原理和效果可以参考之前的博客: http://blog.csdn.net/matrix_space/article/details/30 ...
- POJ1259 The Picnic 最大空凸包问题 DP
POJ1259 给定平面上100个点 求一个最大的凸包,使得它不包含其中任意点,且凸包的顶点是题目所给的点. 枚举凸包左下角的点,顺时针枚举第二个点, 用opt[i][j]记录 i作为第二个点, 且第 ...
- 从csv文件读取数据到二维vector
void ReadDataFromCsv(std::string &filename, std::vector<std::vector<std::string> > & ...
- 11.7NOIP模拟题
/* 有循环节 */ #include<cstdio> #include<cstring> #include<iostream> #include<algor ...
- nginx部署vue项目 解决方案
给前端同事部署了web项目之后,访问发现除了index.html可以访问,其他的路径使用了“伪静态”.比如访问:http://localhost:8081/user/login,访问即报404错误,这 ...
- EntityFramework(转自wiki)
维基百科 Entity Framework (又称ADO.NET Entity Framework) 是微软以 ADO.NET 为基础所发展出来的对象关系对应 (O/R Mapping)解决方案,早期 ...
- 406 Queue Reconstruction by Height 根据身高重建队列
假设有打乱顺序的一群人站成一个队列. 每个人由一个整数对(h, k)表示,其中h是这个人的身高,k是排在这个人前面且身高大于或等于h的人数. 编写一个算法来重建这个队列.注意:总人数少于1100人.示 ...