Linux Shell脚本入门第一步到第N步

前言:

个人认为,Shell的本质就是将需要在终端运行的命令写成一个可运行的文件[可称其为脚本],并通过各种方法使脚本很方便的运行

继续完善中,待更……

参考资料

1、罗列shell中常用的特殊符号:
https://wenku.baidu.com/view/bb0c02a73968011ca30091d7.html
2、shell中条件判断if中的-z到-d的意思:
https://blog.csdn.net/yu132563/article/details/51207331

1. 第一个Shell脚本

cd Shell_Probject/
vim shell01.sh

#!/bin/bash
read string
echo "Hello"
echo -e "World!\n"
echo "$string write"
echo "This is a Test File" >> ./test.txt
# 运行:
./shell01.sh
FirstShell!		# 该参数为运行后再输入的
Hello
World!

FirstShell! write

# 查看该目录下的test.txt文件:
cat test.txt
**** This is a Test File ****
1.1 该Shell脚本的意思:
# 第1行的“#!”是一个约定的标记,它告诉系统这个脚本需要使用哪一种Shell解释器来执行。
# 第2行的“read”命令用于读取运行Shell脚本后的从标准输入中读取一行,并把输入行的每个字段
# 的值指定给变量“string”。
# 第3行的“echo”命令用于向窗口输出文本。
# 第4行的“-e”是用来响应后面的“\n”,形成空行。
# 第5行的"$string"是对应第2行指令的读取标准输入行。
# 第6行的“>”是将前面的字符串定向传输至“./test.txt”文件,会覆盖;如果为“>>”,则是以
# 追加的方式定向传输至“./test.txt”文件,原文件的内容会保存,追加的内容在原内容的下一行。
1.2 运行Shell脚本有两种方法:
# 1.作为可执行程序
# 将上面的代码保存为 shell01.sh,并 cd 到相应目录:
# chmod +x ./shell01.sh            # 使脚本具有执行权限
# chmod 777./shell01.sh            # 使脚本具有777权限
# ./shell01.sh                     # 执行脚本 
# 注: 如果是写成“/shell01.sh”,运行Shell脚本时linux 系统会去Path里寻找有没有叫shell01.sh
# 的,而只有 /bin,/sbin,/usr/bin,/usr/sbin 等在Path里,而通常Shell脚本不在Path里。
# 
# 2.作为解释器参数
# 这种运行方式是 直接运行解释器,其参数就是 shell 脚本的文件名:
# /bin/sh shell01.sh
# 注: 这种方式运行的脚本,不需要在第一行指定解释器信息,写了也没用。 
1.3 运行Shell脚本报错的解决办法:
# 如果是在 Windows 写好 Shell脚本拉到 Linux 下运行,则会出现以下运行报错信息:
# “bash: ./shell01.sh: /bin/bash^M: 解释器错误: 没有那个文件或目录”。
# 多种解决方法:
# 1.运行 Shell脚本前,先输入“sed -i 's/\r//' FileName.sh”,意思是把行尾的\r替换为空。
# 2.运行 Shell脚本前,先输入“dos2unix FileName.sh”,意思是直接转换成Unix格式。
# 3.在vim下的命令行使用命令“:set fileformat=unix”。
# 出现问题的原因:
# Windows中的每行结尾是“<回车 CR><换行 LF>”,即“\r\n”;
# linux中的每行结尾是“<换行 LF>”,即“\n”。
1.4 echo命令的选项:
# echo 选项:
# -e:支持反斜线控制的字符转换
# -n:取消输出后行末的换行符号,内容输出后不换行
# 控制字符       作用
# \\            输出"\"本身
# \a            输出警告音
# \b            退格键,也就是向左删除键
# \c            取消输出行末的换行符。和“-n”选项一致
# \e            Esc键
# \f            换页符
# \n            换行符
# \r            回车键
# \t            制表符,也就是Tab键
# \v            垂直制表符
# \Onnn         按照八进制 ASCII 码表输出字符。其中 0 为数字 0,nnn 是三位八进制数
# \xhh          按照十六进制 ASCH 码表输出字符。其中 hh 是两位十六进制数
# 
# echo显示颜色:,控制选项说明:
# \33[0m		关闭所有属性 
# \33[1m		设置高亮度 
# \33[4m		下划线 
# \33[5m		闪烁 
# \33[7m		反显 
# \33[8m		消隐 
# \33[30m -- \33[37m		设置前景色 
# \33[40m -- \33[47m		设置背景色 
# \33[nA		光标上移n行 
# \33[nB		光标下移n行 
# \33[nC		光标右移n行 
# \33[nD		光标左移n行 
# \33[y;xH		设置光标位置 
# \33[2J		清屏 
# \33[K			清除从光标到行尾的内容 
# \33[s			保存光标位置 
# \33[u			恢复光标位置 
# \33[?25l		隐藏光标 
# \33[?25h		显示光标 

# 字体颜色:30m-37m 黑、红、绿、黄、蓝、紫、青、白
str="jluo"
echo -e "\033[30m ${str}\033[0m"      ## 黑色字体
echo -e "\033[31m ${str}\033[0m"      ## 红色
echo -e "\033[32m ${str}\033[0m"      ## 绿色
echo -e "\033[33m ${str}\033[0m"      ## 黄色
echo -e "\033[34m ${str}\033[0m"      ## 蓝色
echo -e "\033[35m ${str}\033[0m"      ## 紫色
echo -e "\033[36m ${str}\033[0m"      ## 青色
echo -e "\033[37m ${str}\033[0m"      ## 白色

# 背景颜色:40-47  黑、红、绿、黄、蓝、紫、青、白
str="jluo"
echo -e "\033[41;37m ${str} \033[0m"     ## 红色背景色,白色字体
echo -e "\033[41;33m ${str} \033[0m"     ## 红底黄字
echo -e "\033[1;41;33m ${str} \033[0m"   ## 红底黄字 高亮加粗显示
echo -e "\033[5;41;33m ${str} \033[0m"   ## 红底黄字 字体闪烁显示
echo -e "\033[47;30m ${str} \033[0m"     ## 白底黑字
echo -e "\033[40;37m ${str} \033[0m"     ## 黑底白字

2. Shell脚本的流程控制与判断条件

变量的判断条件的比较符
# -eq 等于
# -ne 不等于
# -gt 大于
# -lt 小于
# -ge 大于等于
# -le 小于等于
流程控制
2.1 判断流程
# if判断 Shell脚本版
if [ 条件1 ]
then
        命令1
elif [ 条件2 ]
then
        命令2
else
        命令N
fi

# if判断 终端命令版(一行解决)
if [ 条件1 ]; then 命令1 ; fi

# case判断 Shell脚本版(注:case命令后的“;;”表示break)
case "$Val" in
        Num1) 命令1
        ;;
        Num2) 命令2
        ;;
        Num3) 命令3
        ;;
        *) 命令其他
        ;;
esac
2.2 循环流程
# 02 循环流程-for循环 Shell脚本版
for 变量 in {1..N}			# 常用写法
# for 变量 in 1 2 3 4 N		# 不常用的写法
do
        命令1
        命令2
        命令3
        命令4
        命令N
done

for循环 终端命令版(一行解决)
for 变量 in 1 2 3 4 N ; do 命令1; 命令2; 命令3; 命令N; done;


while循环 Shell脚本版
# 注:while循环与until循环不一样,while循环条件为真则循环,until循环条件为假则循环
变量=0
while [ $变量 -lt 5 ]
do
        命令
#       let "变量++"
        变量=$((变量 + 1))
done

# 无限循环-while循环-01
while :
do
        命令
done

# 无限循环-while循环-02
while true
do
        命令
done


# until循环
# 注:while循环与until循环不一样,while循环条件为真则循环,until循环条件为假则循环
until [ 判断表达式 ]
do
        命令
done
2.3 跳出循环/流程
# 跳出循环-break
# 跳出本层循环

# 跳出循环-continue
# 跳出本次循环,但依旧还在本层循环中
字符串的比较
# 例子,判断文件版本,将下面的程序放到一个Shell脚本
# 笔者注:Shell脚本中的字符串比较与C语言中的strcmp函数对比较规则一致。
# 从字符串的首个字符开始依次比较


NewVerInfo="1.00.10"
OldVerInfo="1.00.10"		# 运行 3
# OldVerInfo="1.00.05"		# 运行 1 和 4
# OldVerInfo="1.00.15"		# 运行 1 和 2

if [ "$NewVerInfo" != "$OldVerInfo" ]
then
	echo -e "== 1 == OldVerInfo != NewVerInfo \n"
fi

if [ "$NewVerInfo" \< "$OldVerInfo" ]
then
	echo -e "== 2 == OldVerInfo > NewVerInfo \n"

elif [ "$NewVerInfo" == "$OldVerInfo" ]
then
	echo -e "== 3 == OldVerInfo = NewVerInfo \n"

elif [ "$NewVerInfo" \> "$OldVerInfo" ]
then
	echo -e "== 4 == OldVerInfo < NewVerInfo \n"

fi

3. Shell脚本的判断条件比较符及其使用

变量的判断条件的比较符
# -e  判断对象是否存在
# -d  判断对象是否存在,并且为目录
# -f  判断对象是否存在,并且为常规文件
# -L  判断对象是否存在,并且为符号链接
# -h  判断对象是否存在,并且为软链接
# -s  判断对象是否存在,并且长度不为0
# -r  判断对象是否存在,并且可读
# -w  判断对象是否存在,并且可写
# -x  判断对象是否存在,并且可执行
# -O  判断对象是否存在,并且属于当前用户
# -G  判断对象是否存在,并且属于当前用户组
# -nt 判断file1是否比file2新 [ "/data/file1" -nt "/data/file2" ]
# -ot 判断file1是否比file2旧 [ "/data/file1" -ot "/data/file2" ]

# -z  判断字符串是否为空
# -n  判断字符串是否不为空
3.1 检测文件(File)是否存在
if [ -f "/Directory/File" ]
then
        echo "文件存在"
fi

if [ ! -f "/Directory/File" ]
then
        echo "文件不存在"
fi
3.2 检测目录(Directory)是否存在
if [ -d "/Directory/" ]
then
        echo "目录存在"
fi

if [ ! -d "/Directory/" ]
then
        echo "目录不存在"
fi
3.3 检测字符串(Char)是否存在
String=
if [ -z "$String" ]
then
        echo "字符串为空"
fi

if [ -n "$String" ]
then
        echo "字符串不为空"
fi

4. Shell脚本的运行符号、字符串的截取

4.1 运行可执行程序附带符号的含义:
# & :表示任务在后台执行
# | :表示管道,上一条命令的输出,作为下一条命令参数(输入)
# && :表示前一条命令执行成功时,才执行后一条命令 
# || :表示上一条命令执行失败后,才执行下一条命令
# > :将正常信息重定向
# &> 或 >& :可将错误信息或者普通信息都重定向输出
4.2 Linux的标准输入、输出、错误:
# 0 ==> stdin 标准输入
# 1 ==> stdout 标准输出
# 2 ==> stderr 标准错误

# 例子:
# 使用命令 touch /tmp/test.txt
# ls /tmp/*.txt
$ /tmp/test.txt
# 在上面的条件下讨论下面的情况:
# 若使用命令 ls /tmp/test.txt 为标准输出,
# 若使用命令 ls /tmp/temp.txt 为标准错误。
# 
# 使用命令 ls /tmp/test.txt 1> /tmp/test.txt ,可将标准输出定向输入到/tmp/test.txt;
# 使用命令 ls /tmp/temp.txt 2> /tmp/test.txt ,可将标准错误定向输入到/tmp/test.txt;
# 使用命令 ls /tmp/texx.txt &> /tmp/test.txt ,可将标准输出或者标准错误定向输入到
# /tmp/test.txt
# ls /tmp/texx.txt &> /tmp/test.txt 等同于 ls /tmp/texx.txt > /tmp/test.txt 2>&1
# 也等同于 ls /tmp/texx.txt > /tmp/test.txt 2>/tmp/test.txt
# 注:个别Linux发行版/版本不支持“>&”符号,需要去掉“&”符号
4.3 Linux字符串的操作:
# 4.3.1 字符串的截取,在终端中输入:
var="/xxx/xxx/xxx/xxx/xxx/test.txt"
echo ${var:4:5}
echo ${var:4}
echo ${var:0-4:3}
echo ${var:0-4}
echo ${#var}

# ${var#*/}:删掉第1个“/”及其左边的字符串
# ${var##*/}:删掉最后1个“/”及其左边的字符串
# ${var%/*}:删掉最后1个“/”及其右边的字符串
# ${var%%/*}:删掉第1个“/”及其右边的字符串
# ${var:start:len}:提取从第start个字符右边数起(第start+1个字符),连续len个长度的字符串,
# ${var:start}:提取从第start个字符右边数起(第start+1个字符)的所有字符串
# ${var:0-start:len}:提取从倒数第start个起,连续len个长度的字符串
# ${var:0-start}:提取从倒数第start个起的字符串
# ${#var}:获得字符串的长度
# 
# 注:
# 1. “#”与“%”的记忆方法:“#”在“$”左边、“%”在“$”右边;单符号为最小匹配、双符号为最大匹配;
# “#*Symbol”:删除第一个“Symbol”(特制某个符号,可以为“/”、“.”等)及其左边的字符串;
# “##*Symbol”:删除最后一个“Symbol”(特制某个符号,可以为“/”、“.”等)及其左边的字符串;
# “%”:删除最后一个“Symbol”(特制某个符号,可以为“/”、“.”等)及其右边的字符串;
# “%%”:删除第一个“Symbol”(特制某个符号,可以为“/”、“.”等)及其右边的字符串;
# 2. “start”与“len”代表某个具体数字:
# 若“start”为5,代表提取第5个字符右边数起的字符(字节为单位),即第6个字符开始;
# 若“len”为2,代表取连续的2个字符(字节为单位)
# 4.3.2 字符串的替换,使用“sed”命令提取字符串

# 新建shell脚本,并将下面的内容放到脚本内
# 主要实现的内容:对“FilePath”文件中行末为“CharSource”的字符替换成“CharTarget”,可用于
# 在网上摘抄程序,对行开头的多个空格替换为tab,或者行结尾去掉多余的空格

#!/bin/sh

# 选择文件
FilePath=/tmp/test.txt

# 原字符,行首符号为"^",行末符号为"$"
# 若要指定行首,CharSource="^xxx";若要指定行末,CharSource="xxx$";
# 也可以不指定,CharSource="xxx"
CharSource=" "

# 目标字符
CharTarget="	"

# 命令格式:
sed -i "s/$CharSource/$CharTarget/g" $FilePath

# 参数说明:
# i 表示就地修改文件
# s 表示替换,d 表示删除
# g 表示每行出现的字符全部替换
# r 表示搜索子目录
# l 表示输出匹配的文件名
# 行首符号为"^",行末符号为"$",不指定为空

# CharSource说明:
# CharSource="^[ ]*"		// 匹配行首一个或者多个字符,字符为[]内的内容,这里为空格
# CharSource="[ ]*$"		// 匹配行尾一个或者多个字符,字符为[]内的内容,这里为空格
# CharSource="^.."			// 匹配行首n个字符,多少个“.”就为多少个字符,这里为2个
# CharSource="..$"			// 匹配行尾n个字符,多少个“.”就为多少个字符,这里为2个
# CharSource="^.\{3\}"		// 匹配行首3个字符
# CharSource=".\{3\}$"		// 匹配行尾3个字符
# 4.3.3 在“类表格”的数据中提取指定的数据


# 举个例子,获取挂载的文件系统的存储,在终端中输入命令:
$ df -h
Filesystem                Size      Used Available Use% Mounted on
/dev/root               200.0M     98.0M    102.0M  49% /
devtmpfs                192.1M         0    192.1M   0% /dev
tmpfs                   320.5M     16.0K    320.4M   0% /tmp
/dev/mtdblock5           80.0M     16.8M     63.2M  21% /home


# 将以下内容加入Shell脚本内:
#!/bin/sh

# 容量在表格中的表头为“Size”,指定想查询容量的文件系统为NandFlash的分区/dev/mtdblock5
SizeSymbol="Size"
FileSysName="/dev/mtdblock5"

# 获取Size的列数
SizeColumn="$( df -h | grep Filesystem | grep -v grep | awk -F ' ' '{for (i=1;i<=NF;i++) {if ($i==Symbol ) {print i}}}' Symbol="$SizeSymbol" )"

# 获取容量大小
Size="$( df -h | grep $FileSysName | grep -v grep | awk -F ' ' '{ print $Column }' Column="$SizeColumn" )"

# 查看Size的列数与/dev/mtdblock5的容量
echo "$SizeColumn"
echo "$Size"


# 运行脚本后:
2
80.0M

5. Shell脚本的计算

#!/bin/sh

a=9
b=3

# 加法:
c=$((a + b))
echo "c = $c "

# 减法:
d=$((a - b))
echo "d = $d "

# 乘法:
e=$((a * b))
echo "e = $e "

# 除法:
f=$((a / b))
echo "f = $f "

# 多次幂:
g=$((a**b))
echo "g = $g "

6. 文件的解压与压缩命令

# 以下命令未经过测试

# 1. “.tar”文件,使用tar命令
解压:tar -xvf FileName.tar
压缩:tar -cvf FileName.tar DirName

# 2. “.gz”文件,使用gunzip、gzip命令
解压1:gunzip FileName.gz
解压2:gzip -d FileName.gz
压缩:gzip FileName

# 3. “.tar.gz”文件,使用tar命令
解压:tar -zxvf FileName.tar.gz
压缩:tar -zcvf FileName.tar.gz DirName

# 4. “.bz2”文件,使用bzip2、bunzip2命令
解压1:bzip2 -d FileName.bz2
解压2:bunzip2 FileName.bz2
压缩:bzip2 -z FileName

# 5. “.tar.bz2”文件,使用tar命令
解压:tar -jxvf FileName.tar.bz2
压缩:tar -jcvf FileName.tar.bz2 DirName

# 6. “.bz”文件,使用bzip2、bunzip2命令
解压1:bzip2 -d FileName.bz
解压2:bunzip2 FileName.bz

# 7. “.tar.bz”文件,使用tar命令
解压:tar -jxvf FileName.tar.bz

# 8. “.z”文件,使用uncompress、compress命令
解压1:uncompress FileName.z
解压2:compress -d FileName.z
压缩:compress FileName

# 9. “.tar.z”文件,使用tar命令
解压:tar -zxvf FileName.tar.z
压缩:tar -zcvf FileName.tar.z DirName

# 10. “.zip”文件,使用unzip、zip命令
解压:unzip FileName.zip
压缩:zip FileName.zip DirName

# 11. “.tar.xz”文件,使用tar命令
解压:tar -Jxvf FileName.tar.xz
压缩:tar -Jcvf FileName.tar.xz DirName

7. 文件属性操作

# 文本属性
# 文件类型[d:目录;-:文件;l:链接文件;b:装置文件里面的可供存储的接口设备(可随机存取装置); 
#        c:装置文件里面的串行端口设备(一次性读取装置)]
# 身份[u:user;g:group;o:others;a:all]
# 权限[r:read 4;w:write 2;x:execute 1]
# 改变方法[+:加入;-:除去;=:设定]

# 更改文件属性:
# 注:[-R],进行递归(recursive)的持续变更
# 更改文件属组:chgrp [-R] 属组名 文件名
# 更改文件属主与文件属组:chown [-R] 属主名:属组名 文件名
# 更改文件权限属性:chmod [-R] xyz 文件或目录
ls -hl /tmp/test.txt
xxx xx [所属主] [所属组] xxxxxxxxxxxxxxxxx


# 更改文件 所属组 的方法:
touch /tmp/test.txt
chgrp bin /tmp/test.txt


# 更改文件 所属主 与 所属组
touch /tmp/test.txt
chown bin /tmp/test.txt
chown root:root /tmp/test.txt


# 修改权限属性的方法:
touch /tmp/test.txt
ls -hl /tmp/test.txt

chmod u=rwx,g=rwx,o=rwx /tmp/test.txt
ls -hl /tmp/test.txt

chmod a-wx /tmp/test.txt
ls -hl /tmp/test.txt

chmod u+wx,g+wx,o+wx test.txt
ls -hl /tmp/test.txt

chmod 444 /tmp/test.txt
ls -hl /tmp/test.txt


# 查看文件的atime(access time,最后的访问时间)、mtime(modify time,最后的修改时间)、
# ctime(change time,创建时间)
ls -lu FileName		# 查看文件的 atime
ls -l FileName		# 查看文件的 mtime
ls -lc FileName		# 查看文件的 ctime

# 修改时间:文件的内容被最后一次修改的时间,我们经常用的ls -l命令显示出来的文件时间就是这个时间,
#   当用vim对文件进行编辑之后保存,它的mtime就会相应的改变
# 访问时间:对文件进行一次读操作,它的访问时间就会改变。例如像:cat、more等操作,但是像之前的
#   state还有ls命令对atime是不会有影响的;
# 状态时间:当文件的状态被改变的时候,状态时间就会随之改变,例如当使用chmod、chown等改变文件
#   属性的操作是会改变文件的ctime的。

8. 文本操作

# 搜索当前目录下的所有子目录
ls -R

# 匹配文本中包含指定数据的行,及其后2行与前3行:
grep -E -A 2 -B 3 "model name" /proc/cpuinfo

# 文件的最宽、最长、字节数、字符数
wc -L /proc/mounts
wc -l /proc/mounts
wc -c /proc/mounts
wc -m /proc/mounts

# 排序:升序、降序
sort -f
sort -t

# 查看文件头、文件尾
head -n 3 /proc/mounts
tail -n 3 /proc/mounts

随便写写系列

1. RTC的使用
# 笔者注:
# 当前的系统时间分为 软件时间 与 硬件时间

# 1.1 软件时间 的 查看方式
$ date
Wed May  2 08:08:11 UTC 2018

$ cal
      May 2018
Su Mo Tu We Th Fr Sa
       1  2  3  4  5
 6  7  8  9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31

# 1.2 软件时间 的 设置方式
$ date -s 2018-05-02
$ date -s 08:08:08


# 2 硬件时间 的 查看方式
$ hwclock -r
Sat Jan  1 00:03:35 2000  0.000000 seconds

$ cat /sys/class/rtc/rtc0/date
2000-01-01

$ cat /sys/class/rtc/rtc0/time
00:02:56


# 3.1 将 软件时间 设置进 硬件时间
$ hwclock -w

# 3.2 将 硬件时间 设置进 软件时间(同步软件时间)
$ hwclock -s
2. curl的使用
#!/bin/sh

# URL的定义:在WWW上,每一信息资源都有统一的且在网上唯一的地址,该地址就叫URL(统一资源定位符),
# 它是WWW的统一资源定位标志,就是指网络地址。
# cURL 为 CommandLine Uniform Resource Locator

# HttpWay可以为“GET”、"POST"
HttpWay="GET"
# Url可以为“www.baidu.com”等
Url="www.baidu.com"
# 命令格式:
curl -i -X $HttpWay $Url

# 参数说明:
# i:返回请求url状态码
# X:使用HTTP协议的请求方式
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值