Shell常用命令大全之入门篇
本文为shell的一个系列教程,分为入门篇、命令篇、实战篇
教程里尽量减少复杂的文字描述,不求全,但求精,以实例为主,目标是让读者快速上手shell。
以下为本教程的第一部分《入门篇》,欢迎读者拍砖及找BUG,后续会根据反馈进行修改及补充。
CSDN的Markdown生成的目录显示符号有一点小问题,大家以详细内容中的标题为准。
- 入门篇
- 第一招 HelloWorld
- 第一式echo
- 第二招 判断
- 第一式if
- 判断原理
- 第二式test 和
- 文件测试
- 字符串比较
- 整数比较
- 第三式
- 第一式if
- 第三招循环
- 第一式for
- 第二式whileuntil
- 第四招变量
- 第一式整数
- 整数的运算
- 第二式字符串
- 替换
- 截取子串
- 通配删除
- 第三式数组
- 普通数组
- 关联数组
- 第四式将命令执行结果存入变量
- 与
- 换行符处理
- 第一式整数
- 第五招重定向
- 标准输入流标准输出流标准错误流
- 重定向方式一览表
- 第一式重定向标准输出流stdout
- 第二式重定向标准错误流stderr
- 第三式重定向标准输入流stdin
- 第六招管道
- 第一式管道的基本功能
- 第二式管道与whileread组合
- 第三式管道与xargs组合
- 第七招通配
- shell通配的原理
- 通配符一览表
- 第一式
- 第二式
- 第三式
- 第四式
- 第一招 HelloWorld
入门篇
第一招 HelloWorld
第一式:echo
echo "Hello World"
echo -n "Hello World" # 不带换行
echo -e '\e[0;33;1mHello\e[0m World' # 带颜色的玩法 echo -e '\e[0;33;4mHello\e[0m World' # 带颜色+下划线 echo -e '\e[0;33;5mHello\e[0m World' # 带颜色+闪烁
格式为 \e[背景色;前景色;高亮格式m
,请阅读详细文档后使用正确的姿势进行装逼。
第二招 判断
第一式:if
if true then echo "Hello World" else echo "Bug" fi if false then echo "Hello World" elif true then echo "Bug" else echo "Bee" fi
判断原理
if
、elif
会执行它后面跟着的命令,然后看返回值是否为0
,如果为0
则执行then
下面的语句块,否则执行else
下面的语句块。
[linuxidc@Ubuntu:~]$ true [linuxidc@ubuntu:~]$ echo $? 0 [linuxidc@ubuntu:~]$ false [linuxidc@ubuntu:~]$ echo $? 1
注:
true
、false
事实上也为一个命令,true
的返回码必为0
,false
的返回码必为1
$?
为shell
内置变量,用于存放上一个命令的返回码
第二式:test、[ ] 和 [[ ]]
test
、[ ]
、[[ ]]
实际上都是shell
中的命令,执行之后会返回1
或0
,而这几个命令与if
相结合可以达到我们所需要的许多判断功能,例如测试字符串是否为空的三种写法:
s="" if [ -z ${s} ] then echo "empty" fi if [[ -z ${s} ]] then echo "empty" fi if test -z ${s} then echo "empty" fi
事实上,if
后的[ ]
、[[ ]]
、test
命令都是可以单独执行的,而根据if
的判断原理,后续执行哪个分支也是由[ ]
、[[ ]]
、test
的返回值来决定的,以下是单独执行它们的效果:
[linuxidc@ubuntu:~]$ s="" [linuxidc@ubuntu:~]$ [ -z "${s}" ] [linuxidc@ubuntu:~]$ echo $? 0 [linuxidc@ubuntu:~]$ s="abc" [linuxidc@ubuntu:~]$ test -z "${s}" [linuxidc@ubuntu:~]$ echo $? 1 [linuxidc@ubuntu:~]$ s="123" [linuxidc@ubuntu:~]$ [[ 100 -lt ${s} ]] [linuxidc@ubuntu:~]$ echo $? 0
在性能方面[ ]
和test
性能基本相同,[[ ]]
性能是最高的,为前两者的5
倍左右(以-d
运算符测试),所以建议尽量使用[[ ]]
提高脚本性能。
文件测试
运算符 | 描述 | 示例 |
---|---|---|
-e filename | 如果 filename 存在,则为真 | [ -e /var/log/syslog ] |
-d filename | 如果 filename 为目录,则为真 | [ -d /tmp/mydir ] |
-f filename | 如果 filename 为常规文件,则为真 | [ -f /usr/bin/grep ] |
-L filename | 如果 filename 为符号链接,则为真 | [ -L /usr/bin/grep ] |
-r filename | 如果 filename 可读,则为真 | [ -r /var/log/syslog ] |
-w filename | 如果 filename 可写,则为真 | [ -w /var/mytmp.txt ] |
-x filename | 如果 filename 可执行,则为真 | [ -L /usr/bin/grep ] |
filename1 -nt filename2 | 如果 filename1 比 filename2 新,则为真 | [ /tmp/install/etc/services -nt /etc/services ] |
filename1 -ot filename2 | 如果 filename1 比 filename2 旧,则为真 | [ /boot/bzImage -ot arch/i386/boot/bzImage ] |
字符串比较
运算符 | 描述 | 示例 |
---|---|---|
-z string | 如果 string 长度为零,则为真 | [ -z "${myvar}" ] |
-n string | 如果 string 长度非零,则为真 | [ -n "${myvar}" ] |
string1 = string2 | 如果 string1 与 string2 相同,则为真 | [ "${myvar}" = "abc" ] |
string1 != string2 | 如果 string1 与 string2 不同,则为真 | [ "${myvar}" != "abc" ] |
string1 < string | 如果 string1 小于 string2,则为真 | [ "${myvar}" \< "abc" ] [[ "${myvar}" < "abc" ]] |
string1 > string | 如果 string1 大于 string2,则为真 | [ "${myvar}" \> "abc" ] [[ "${myvar}" > "abc" ]] |
注意:
- 在字符串两边加上”“防止出错
<
和>
是字符串比较,不要错用成整数比较- 如果是在
[ ]
中使用<
和>
,需要将它们写成\<
和\>
整数比较
运算符 | 描述 | 示例 |
---|---|---|
num1 -eq num2 | 等于 | [ 3 -eq $mynum ] |
num1 -ne num2 | 不等于 | [ 3 -ne $mynum ] |
num1 -lt num2 | 小于 | [ 3 -lt $mynum ] |
num1 -le num2 | 小于或等于 | [ 3 -le $mynum ] |
num1 -ge num2 | 大于或等于 | [ 3 -ge $mynum ] |
第三式:&&、||
&& 可以用来对两个判断语句求与 |
---|
if [ -n "abc" ] && [ -n "aa" ] |
if [[ -n "abc" ]] && [[ -n "aa" ]] |
if test -n "abc" && test -n "aa" |
if [[ -n "abc" && -n "aa" ]] |
注:只有[[ ]]
才允许把&&
写在里面
|| 可以用来对两个判断语句求或 |
---|
if [ -n "abc" ] || [ -n "aa" ] |
if [[ -n "abc" ]] || [[ -n "aa" ]] |
if test -n "abc" || test -n "aa" |
if [[ -n "abc" || -n "aa" ]] |
小技巧
&&
、||
还可以用来拼接命令,达到按前一个命令成功与否来决定是否执行后一个命令的效果
cd /data && ls # 当`cd /data`返回0(即成功)时才执行后面的`ls` cd /data || cd /root # 当`cd /data`返回非0(即失败)时才执行后面的`cd /root`
第三招:循环
第一式:for
for i in {1..100} do echo ${i} done
注:
{1..100}
属于通配的一种写法,展开会是1 2 3 ... 100
(1~100以空格隔开)这样的字串。例如
for i in 1 2 3;
这样的语句,for
会将1
、2
、3
依次赋值于i
进行循环,而对于通配的情况,for
则会将通配展开后将里面的每一项依次赋值于i
进行循环。
for i in `seq 100` do echo ${i} done for i in `seq 1 2 100` do echo ${i} done
注:
seq
本身为一个命令,用于输出数字组成的序列,如seq 100
会生成并输出1 2 3 ... 100
(1~100以换行符隔开)这样的序列,而seq 1 2 100
则会生成并输出1 3 5 ... 99
(以1开始,2为公差的等差数列中小于100的项,以换行符隔开)。- 反引号(`)之间的命令会被执行,其输出结果会转换成一个变量,故上面的
for in
会依次取出seq
的执行结果赋值于i
进行循环。
for ((i = 0; i < 100; i++)) do echo ${i} done for ((i = 0; i < 100; i+= 2)) do echo ${i} done
注:
以上与C语言式的for
循环语法基本相同,区别在于双重括号:(( ))
第二式:while、until
i=0 while [[ ${i} -lt 100 ]] do echo ${i} ((i++)) done
i=0 until [[ ${i} -ge 100 ]] do echo ${i} ((i++)) done
注:
while
和until
的判断原理与if
是类似的,它会执行并它后面跟着的命令,不同点在于:
while
是后面语句返回值为0
,则执行循环中的语句块,否则跳出循环;until
则是后面语句返回值非0
,则执行循环中的语句块,否则跳出循环。