Shell脚本基础入门
Bash注释
Bash只支持单行注释,使用 #
开头的都被当作注释语句:
整行注释
echo hello world # 行尾注释
通过Bash的一些特性,可以取巧实现多行注释:
: '
注释1
注释2
'
: <
但是,别闲的蛋疼去用取巧的多行注释,安心用 #
来注释。
Bash基本数据类型
Bash中基本数据类型只有字符串类型,连数值类型都没有(declare -i
可强制声明数值类型)。
比如:
都会当作字符串
echo haha
echo 1234
Bash字符串串联
Bash中字符串的串联操作,直接将两段数据连接在一起即可,不需要任何操作符。
例如:
echo "junma""jinlong"
echo 1234 5678
命令基本知识
变量赋值和引用变量
a=3
echo $a
a="www.junmajinlong.com"
echo $a
a='hello world'
echo $a
Shell中可以引用未定义的变量:
echo $xyzdefabc
可以定义空变量:
a=
echo $a
变量替换
变量替换是指在命令开始执行前,Shell会先将变量的值替换到引用变量的位置处。
例如:
a="hello"
echo $a world
在echo命令开始执行前,Shell会取得变量a的值hello,并将它替换到命令行的 $a
处。于是,在echo命令开始执行时,命令行已经变成:
echo hello world
除了变量替换,Shell还会做其它替换:
- 命令替换
- 进程替换
- 算术运算替换
- 大括号扩展
- 波浪号扩展
- 路径扩展
这些扩展和替换,都是Shell在调用命令之前就完成的,这和其它语言解析代码的方式不一样。
学习Shell如何做命令行解析很重要,如果不掌握命令行解析,当遇到命令行语法错误后很可能会花掉大量无谓的时间去调试命令。而掌握命令行解析后,就会对命令生命周期了如执掌,不敢说一次就能写对所有命令行,但能节省大量调试时间,对写命令行和写脚本的能力也会上升一个层次。
命令替换
使用反引号或 $()
可以执行命令替换。
cmd
$(cmd)
命令替换是指先执行cmd,将cmd的输出结果替换到 $()
或反引号位置处。
例如:
echo id root
echo $(id root)
在echo命令执行前,会先执行id命令,id命令的执行结果:
$ id root
uid=0(root) gid=0(root) groups=0(root)
所以会将结果 uid=0(root) gid=0(root) groups=0(root)
替换 $(id root)
。于是,echo命令开始执行时,命令行已经变成了:
echo uid=0(root) gid=0(root) groups=0(root)
算术运算
$[]
或 $(())
或let命令可以做算术运算。
let是单独的命令,不能写在其它命令行中。
a=3
let a=a+1
echo $a
$[]
和 $(())
可以写在命令行内部,Shell在解析命令行的时候,会对它们做算术运算,然后将运算结果替换到命令行中。
a=33
echo $[a+3]
echo $((a+3))
因为变量替换先于算术替换,所以,使用变量名或引用变量的方式都可以:
a=333
echo $[$a+3]
echo $(($a+3))
退出状态码
每个命令执行后都会有对应的进程退出状态码,用来表示该进程是否是正常退出。
所以,在命令行中,在Shell脚本中,经常会使用特殊变量 $?
判断最近一个前台命令是否正常退出。
通常情况下,如果 $?
的值:
- 为0,表示进程成功执行,即正常退出
- 非0,表示进程未成功执行,即非正常退出
- 但非0退出状态码并不一定表示错误,也可能是正常逻辑的退出
另外,在Shell脚本中,所有条件判断(比如if语句、while语句)都以0退出状态码表示True,以非0退出状态码为False。
exit命令
exit命令可用于退出当前Shell进程,比如退出当前Shell终端、退出Shell脚本,等等。
exit [N]
exit可指定退出状态码N,如果省略N,则默认退出状态码为0,即表示正确退出。
后台执行命令&
在命令的结尾使用 &
符号,可以将这个命令放入后台执行。
命令放入后台后,会立即回到Shell进程,Shell进程会立即执行下一条命令(如果有)或退出。
使用 $!
可以获取最近一个后台进程的PID。
sleep 20 &
echo $!
使用 wait
命令可以等待后台进程(当前Shell进程的子进程)完成:
wait [n1 n2 n3 ...]
不给定任何参数时,会等待所有子进程(即所有后台进程)完成。
sleep 5 &
wait
echo haha
多命令组合
Shell中有多种组合多个命令的方式。
1.cmd1退出后,执行cmd2
cmd1;cmd2
2.cmd1正确退出(退出状态码为0)后,执行cmd2
cmd1 && cmd2
3.cmd1不正确退出后,执行cmd2
cmd1 || cmd2
4.逻辑结合: &&
和 ||
可以随意结合
cmd1正确退出后执行cmd2,cmd2正确退出后执行cmd3
cmd1 && cmd2 && cmd3...
cmd1正确退出则执行cmd2,cmd1不正确退出会执行cmd3
cmd1正确退出,但cmd2不正确退出,也会执行cmd3
cmd1 && cmd2 || cmd3
cmd1正确退出会执行cmd3
cmd1不正确退出会执行cmd2,cmd2正确退出会执行cmd3
cmd1 || cmd2 && cmd3
5.将多个命令分组:小括号或大括号可以组合多个命令
小括号组合的多个命令是在子Shell中执行
即会先创建一个新的Shell进程,在执行里面的命令
(cmd1;cmd2;cmd3)
大括号组合的多个命令是在当前Shell中执行
大括号语法特殊,要求:
1.开闭括号旁边都有空白,否则语法解析错误(解析成大括号扩展)
2.写在同一行时,每个cmd后都要加分号结尾
3.多个命令可分行书写,不要求分号结尾
{ cmd1;cmd2;cmd3; }
{
cmd1
cmd2
cmd3
}
基本重定向
软件设计认为,程序应该有一个数据来源、数据出口和报告错误的地方。在Linux系统中,每个程序默认都会打开三个文件描述符(file descriptor,fd):
- fd=0:标准输入,表示程序默认从哪里读取数据
- fd=1:标准输出,表示程序默认将数据输出到哪里
- fd=2:标准错误,表示程序默认将错误信息输出到哪里
文件描述符,说白了就是系统为了跟踪打开的文件而分配给它的一个数字,这个数字和文件有对应关系:从文件描述符读取数据,即表示从对应的文件中读取数据,向文件描述符写数据,即表示向对应文件中写入数据。
Linux中万物皆文件,文件描述符也是文件。默认:
- fd=0的标准输入是/dev/stdin文件
- fd=1的标准输出是/dev/stdout文件
- fd=2的标准错误是/dev/stderr文件
这些文件默认又是各个终端的软链接文件:
$ ls -l /dev/std*
lrwxrwxrwx 1 root root 15 Jan 8 20:26 /dev/stderr -> /proc/self/fd/2
lrwxrwxrwx 1 root root 15 Jan 8 20:26 /dev/stdin -> /proc/self/fd/0
lrwxrwxrwx 1 root root 15 Jan 8 20:26 /dev/stdout -> /proc/self/fd/1
$ ls -l /proc/self/fd/
lrwx------ 1 root root 64 Jan 16 10:40 0 -> /dev/pts/0
lrwx------ 1 root root 64 Jan 16 10:40 1 -> /dev/pts/0
lrwx------ 1 root root 64 Jan 16 10:40 2 -> /dev/pts/0
lr-x------ 1 root root 64 Jan 16 10:40 3 -> /proc/75220/fd
所以,默认情况下读写数据都是终端,例如:
数据输出到终端
$ echo haha
$ cat /etc/fstab
从终端读取数据
$ cat
hello # 在终端输入
hello # 在终端输出
world # 在终端输入
world # 在终端输出
^C
改变文件描述符对应的目标,可以改变数据的流向。比如标准输入fd=1默认流向是终端设备,若将其改为/tmp/a.log,便能让数据写入/tmp/a.log文件中而不再是终端设备中。
在Shell中,这种改变文件描述符目标的行为称为 重定向,即重新确定数据的流向。
其实,文件描述符有很多类操作,包括fd的重定向、fd的分配(open,即打开文件)、fd复制(duplicate)、fd的移动(move)、fd的关闭(close)。现在只介绍基础重定向操作。
Shell中,基础重定向操作有以下几种方式:
[n]>file
:覆盖式输出重定向,输出到fd=n的数据改变流向输出到file文件中,file不存在则创建,file存在则先清空再写入数据- 省略n时
>file
,等价于1>file
,即标准输出覆盖重定向到file文件中 [n]>>file
:追加式输出重定向,输出到fd=n的数据改变流向输出到file文件的尾部,file不存在则创建,file存在则直接追加在文件尾部- 省略n时
>>file
,等价于1>>file
,即标准输出追加重定向到file文件中 [n]<file< code>:输入重定向,以读取模式打开file文件并分配fd=n,file不存在则报错<ul><li>省略n时<code><file< code>,等价于<code>0<file< code>,即直接从file中读数据</file<></code></file<></code></li><li>通常程序都只从fd=0中读数据,所以当n不等于0时,需要多做一步操作<code>3<file <&3< code>,看不懂先跳过</file></code></li></ul></file<>
&>file
:这是特殊的重定向方式,表示将标准错误和标准输出都重定向到file文件中,等价于>file 2>&1
&>>file
:这是特殊的重定向方式,表示将标准错误和标准输出都追加到file文件中,等价于>>file 2>&1
另外,经常用于输出的一个特殊目标文件是/dev/null,它是空设备,可以直接丢掉所有写入它的数据。
echo www.junmajinlong.com >/dev/null
curl -I www.junmajinlong.com 2>/dev/null >/tmp/a.log
cat
一个经常用的技巧是清空文件的方式:
$ cat /dev/null >file
$ >file
区分cat
Original: https://www.cnblogs.com/f-ck-need-u/p/12275851.html
Author: 骏马金龙
Title: 一篇文章Shell脚本快速入门
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/529494/
转载文章受原作者版权保护。转载请注明原作者出处!