一、注释
书写脚本的要求:
- 脚本第一行要求使用 shebang(#!) 符号指定一个脚本的解释器,如 #!/bin/bash、#!/bin/sh、#!/usr/bin/env python等
- 脚本文件使用 # 或 << 符号实现单行或多行注释,被注释的关键词或代码将不被执行,如记录脚本功能、版本、作者联系方式等。
- 脚本内容是从上往下顺序执行,一行是一条命令。
[root@localhost jiaofan]# vi a.sh
[root@localhost jiaofan]# sh a.sh
hello world
[root@localhost jiaofan]# cat a.sh
#!/bin/bash
<<COMMENT
Author:jiaofan
Date:20220208
Version:1.0
Description:
COMMENT
echo "hello world"
[root@localhost jiaofan]#
注:<<符号后面的关键词可以使任意字符串,但是前面使用什么关键词,结束注释时必须使用相同的关键词。如果从<<ABC开始注释,则结束注释信息时也必须使用ABC(字母区分大小写)
二、脚本执行方式(4种方式)
1、脚本文件自身没有可执行权限
默认情况下,脚本是没有执行权限的,无法直接执行,但是 bash 或者 sh 这样的解释器,可以将脚本文件作为参数(读取脚本文件中的内容)来执行脚本
[root@localhost jiaofan]# ./a.sh
-bash: ./a.sh: 权限不够
[root@localhost jiaofan]# ll a.sh
-rw-r--r--. 1 root root 98 2月 8 15:10 a.sh
[root@localhost jiaofan]# sh a.sh
hello world
[root@localhost jiaofan]# bash a.sh
hello world
2、脚本文件具有可执行权限
[root@localhost jiaofan]# chmod +x a.sh #<==增加可执行权限
[root@localhost jiaofan]# ./a.sh #<==相对路径执行
hello world
[root@localhost jiaofan]# /root/jiaofan/a.sh #<==绝对路径执行
hello world
3、开启子进程执行的方式
[root@localhost jiaofan]# ./a.sh
hello world
[root@localhost jiaofan]# sh a.sh
hello world
[root@localhost jiaofan]# bash a.sh
hello world
4、不开启子进程的执行方式(即当前进程)
[root@localhost jiaofan]# . a.sh
hello world
[root@localhost jiaofan]# source a.sh
hello world
5、开启子进程和不开启子进程的区别
可以理解为,当前终端是一个进程,如果不开启子进程执行exit,就等于在当前终端输入exit。如果开启子进程,等于另外开了一个进程,然后退出另外一个进程,对父进程没有影响。下面是案例:
[root@localhost jiaofan]# cat a.sh
#!/bin/bash
exit
[root@localhost jiaofan]# bash a.sh #<==开启子进程
[root@localhost jiaofan]#
[root@localhost jiaofan]# source a.sh #<==不开启子进程
Connection closed by foreign host.
Disconnected from remote host(159) at 15:51:48.
Type `help' to learn how to use Xshell prompt.
[c:\~]$ #<==直接退出
三、在脚本中实现数据的输入和输出
1、输出:echo
echo [ 选项 ] 字符串
[ 选项 ]
-n:不换行,默认echo换行,可以指定-n参数不换行
-e :可以让 echo 命令识别\后面的转移符号含义。转义符好如下图
符号 | 功能描述 |
---|
\b | 退格键(Backspace)左移一位 | \f | 换行但光标扔留在原来的位置 | \n | 换行且光标移至行首 | \r | 光标移至行首,但不换行 | \t | 插入Tab键 | \ | 打印\ | \033或者\e | 设置终端属性,如字体颜色、背景颜色、定位光标等 |
应用案例:
1)-e:
[root@localhost jiaofan]# echo "\t" #<==没有-e选项,不支持\字符,所以直接输入\t
\t
[root@localhost jiaofan]# echo -e "|\t|"
| |
[root@localhost jiaofan]#
2)-t:
[root@localhost jiaofan]# echo -e "hello\tworld"
hello world
[root@localhost jiaofan]#
输出hello 后,在输入Tab缩进,最后输出world,最终结果就是:hello world
3)-b:
[root@localhost jiaofan]# echo -e "hello\be world"
helle world
[root@localhost jiaofan]# echo -e "hello\b\be world"
hele world
[root@localhost jiaofan]#
第一个输出hello,然后光标左移一位,接着输出e world,原有的字母o被新字符e代替了。注意-e和后面的选项要有最少一个空格。
4)-f:
[root@localhost jiaofan]# echo -e "hello\f world"
hello
world
[root@localhost jiaofan]#
输出hello之后换行,但是光标依然在原来的位置,也就是换行后的第6位。 5)\e或\033:下面 把world加粗
[root@localhost jiaofan]# echo -e "hello \033[1mworld\033[0m"
hello world
[root@localhost jiaofan]# echo -e "hello \e[1mworld\e[0m"
hello world
[root@localhost jiaofan]#
加粗显示world,\033或者\e 后面跟不同的代码可以设置不同的终端属性,1m是让终端粗体显示字符串,最后的\033[0m或者\e[0m是在加粗以后关闭属性设置。如果没有使用0m关闭属性设置,则之后终端中所有的字符串都显示粗体显示。
echo -e "hello\t\e[4mworlk\e[0m" #<==加下划线后输出world
echo -e "hello\t\e[5mworlk\e[0m" #<==闪烁显示world
echo -e "hello\t\e[30mworlk\e[0m" #<==黑色显示world
echo -e "hello\t\e[31mworlk\e[0m" #<==红色显示world
echo -e "hello\t\e[32mworlk\e[0m" #<==绿色显示world
echo -e "hello\t\e[33mworlk\e[0m" #<==棕色显示world
echo -e "hello\t\e[34mworlk\e[0m" #<==蓝色显示world
echo -e "hello\t\e[35mworlk\e[0m" #<==紫色显示world
echo -e "hello\t\e[36mworlk\e[0m" #<==蓝绿色显示world
echo -e "hello\t\e[37mworlk\e[0m" #<==亮灰色显示world
echo -e "hello\t\e[38mworlk\e[0m" #<==亮黄色显示world
echo -e "hello\t\e[44mworlk\e[0m" #<==绿色背景显示world
echo -e "hello\t\e[42mworlk\e[0m" #<==蓝色背景显示world
echo -e "hello\t\e[32;44mworlk\e[0m" #<==绿色字体,蓝色背景显示world
定义在屏幕上第几行第几个位置显示
[root@localhost jiaofan]# clear;echo -e "hello\e[3;10Hworlk\e[0m" #<==在第三行第10列显示world
hello
worlk
[root@localhost jiaofan]#
[root@localhost jiaofan]# clear;echo -e "hello\e[3Hworlk\e[0m" #<==在第三行显示world
hello
worlk
[root@localhost jiaofan]#
2、输出:printf
printf 命令可以格式化输出,默认不会自动换行。
printf [ 格式 ] 参数
常用格式字符串功能描述
格式字符 | 功能描述 |
---|
%d 或者 %i | 十进制整数 | %o | 八进制整数 | %x | 十六进制整数 | %u | 无符号十进制整数 | %f | 浮点数(小数点数) | %s | 字符串 | \b | 退格键(backspace) | \f | 换行但光标扔停留在原来的位置 | \n | 换行且光标移至行首 | \r | 光标移至行首,但不换行 | \t | Tab键 |
1)屏幕显示12
[root@localhost jiaofan]# printf "%d" 12
12[root@localhost jiaofan]#
12[root@localhost jiaofan]# printf "%d" bac #<==bac不是数字,所以无效
-bash: printf: bac: 无效数字
0[root@localhost jiaofan]# printf "%d\n" 12 #<==加了换行符
12
[root@localhost jiaofan]#
2)%5d和%-5d
[root@localhost jiaofan]# printf "|%-5d|\n" 12
|12 |
[root@localhost jiaofan]# printf "|%5d|\n" 12
| 12|
[root@localhost jiaofan]#
- %5d 设置了打印宽度为5,以右对齐的方式显示整数12。
- %-5d 设置了打印宽度为5,以左对齐的方式显示整数12。
3)十进制和八进制转换
[root@localhost jiaofan]# printf "%o\n" 10 #<==十进制的10 转换成八进制
12
[root@localhost jiaofan]# printf "%d\n" 012 #<==0开头代表八进制
10
4)十进制转换成十六进制转换
[root@localhost jiaofan]# printf "%x\n" 10
a
[root@localhost jiaofan]# printf "%d\n" 0xa #<==0x开头代表十六进制
10
5)整数%d的最大范围 9223372036854775807
[root@localhost jiaofan]# printf "%d\n" 999999999999999999999999999999
-bash: printf: 警告: 999999999999999999999999999999: 数值结果超出范围
9223372036854775807
注:如果需要打印这样的大数,需要用到%u,%u最大范围是 18446744073709551615
6)打印小数
[root@localhost jiaofan]# printf "%f\n" 3.88 #<==打印小数3.8
3.880000
[root@localhost jiaofan]# printf "%.3f\n" 3.88 #<==打印小数3.8,并保留3位小数
3.880
[root@localhost jiaofan]# printf "|%8.3f|\n" 3.88 #<==打印小数3.8,一共占八位,小数点后占其中三位
| 3.880|
[root@localhost jiaofan]# printf "|%-8.3f|\n" 3.88 #<==打印小数3.8,并右对齐
|3.880 |
7)打印字符串
[root@localhost jiaofan]# printf "|%10s|\n" "hello"
| hello|
[root@localhost jiaofan]# printf "%s\t\t%s\n" "hello" "world" #<==中间占两个制表符
hello world
3、输入:read
read [ 选项 ] [ 变量名 ]
read 常用选项
选项 | 功能 |
---|
-p | 显示提示信息 | -t | 设置读入数据的超时时间 | -n | 设置读取n个字符后结束,而默认会读取标准输入的一整行内容 | -r | 支持读取\n,而默认read 命令理解\为特殊符号(转义符) | -s | 静默模式,不显示标准输入的内容(Silent mode) |
1)读取键盘输入的内容
[root@localhost jiaofan]# read key1
123
[root@localhost jiaofan]# echo $key1
123
[root@localhost jiaofan]# read key1 key2 key3
11 22 33
[root@localhost jiaofan]# echo $key1--$key2--$key3
11--22--33
[root@localhost jiaofan]#
2)-p:输出提示信息
[root@localhost jiaofan]# read -p "请输入用户名" user
请输入用户名123
[root@localhost jiaofan]# echo $user
123
3)-t:设置超时时间
[root@localhost jiaofan]# read -t 3 -p "请输入用户名:" user
请输入用户名:[root@localhost jiaofan]# #<==三秒不管就自己退出了
4)-r:可以读取\
[root@localhost jiaofan]# read key
\111
[root@localhost jiaofan]# echo $key
111
[root@localhost jiaofan]# read -r key1
\ABC
[root@localhost jiaofan]# echo $key1
\ABC
5)密码不在屏幕上读出来
[root@localhost jiaofan]# read -s -p "请输入密码:" pass
请输入密码:[root@localhost jiaofan]# echo $pass
123456
[root@localhost jiaofan]#
四、输入输出重定向
在linux 系统中输出可以分为标准输出和标准错误输出。标准输出的文件描述符为1,标准错误输出的文件描述符为2。而标准输入的文件描述符则为0。
符号 | 功能 |
---|
> 或者 >> | 标准输出信息重定向,>覆盖原文件信息,>>重定向到原文件的后面 | 1> 或者 1>> | 等于 > 或者 >> | 2> 或者 2>> | 标准错误重定向,>覆盖原文件信息,>>重定向到原文件的后面 | 2>&1 | 将错误输出重定向到标准正确输出 | 1>&2 | 将标准正确输出重定向到错误输出 | < 或者 << | 输入重定向 |
1)> 和>>
[root@localhost jiaofan]# ls /etc/hosts #<==标准输出
/etc/hosts
[root@localhost jiaofan]# ls /nofile #<==错误输出
ls: 无法访问/nofile: 没有那个文件或目录
[root@localhost jiaofan]# ls /etc/hosts > test.txt #<==标准输出重定向
[root@localhost jiaofan]# cat test.txt
/etc/hosts
[root@localhost jiaofan]# ls /nofile 2> test.txt #<==错误重定向
[root@localhost jiaofan]# cat test.txt
ls: 无法访问/nofile: 没有那个文件或目录
[root@localhost jiaofan]# ls /etc/hosts >> test.txt #<==标准输出重定向(追加)
[root@localhost jiaofan]# cat test.txt
/etc/hosts
/etc/hosts
[root@localhost jiaofan]# ls /nofile 2>> test.txt #<==错误重定向(追加)
[root@localhost jiaofan]# cat test.txt
ls: 无法访问/nofile: 没有那个文件或目录
ls: 无法访问/nofile: 没有那个文件或目录
2)既有错误输出又有标准输出,而且要输出到不同文件
[root@localhost jiaofan]# ls -l /etc/hosts /nofile > ok.txt 2> error.txt
[root@localhost jiaofan]# cat ok.txt
-rw-r--r--. 1 root root 158 6月 7 2013 /etc/hosts
[root@localhost jiaofan]# cat error.txt
ls: 无法访问/nofile: 没有那个文件或目录
2)&> 和 &>> :
- &> :符号可以同时将标准输出和错误输出都重定向到同一个文件(覆盖)。
- &>>:符号可以实现追加重定向。
[root@localhost jiaofan]# ls -l /etc/hosts /nofile &> test.txt
[root@localhost jiaofan]# cat test.txt
ls: 无法访问/nofile: 没有那个文件或目录
-rw-r--r--. 1 root root 158 6月 7 2013 /etc/hosts
[root@localhost jiaofan]# ls -l /etc/passwd /oops &>> test.txt
[root@localhost jiaofan]# cat test.txt
ls: 无法访问/nofile: 没有那个文件或目录
-rw-r--r--. 1 root root 158 6月 7 2013 /etc/hosts
ls: 无法访问/oops: 没有那个文件或目录
-rw-r--r--. 1 root root 1281 2月 8 20:33 /etc/passwd
[root@localhost jiaofan]#
3)2>&1、1>&2 :最后的三张图帮助理解这两个的含义。
[root@localhost jiaofan]# ls /nofile 2>&1
ls: 无法访问/nofile: 没有那个文件或目录
[root@localhost jiaofan]# echo "hello" 1>&2
hello
4)在linux中 /dev/null ,这是一个无底洞,无论往该文件写多少数据,都会被系统吞噬、丢弃。
[root@localhost jiaofan]# ls /etc/hosts /mofile &> /dev/null
5)<< 输入重定向
五、各种引号的使用
符号 | 优先级 | 作用 |
---|
双引号"" | 优先级最小 | 引用一个整体 | 单引号’’ | 优先级若于反引号,高于双引号 | 引用一个整体,且单引号内的特殊字符不在特殊 | 反引号`` | 优先级最高,优先执行 | 优先执行,并返回结果 | $()组合符号 | 类似于反引号 | 优先执行,并返回结果,支持嵌套 |
1)双引号与单引号的区别:屏蔽特殊字符含义
[root@localhost jiaofan]# test=14
[root@localhost jiaofan]# echo "$test"
14
[root@localhost jiaofan]# echo '$test'
$test
2)反引号
[root@localhost jiaofan]# tar -czf log-`date +%Y%m%d`.tar.gz log.txt
先执行date +%Y%m%d 得到 20220208 时间,然后执行tar -czf log-20220208.tar.gz log.txt ,得到结果。
3)$()组合符号与反引号的区别
都是优先级最高,但是$()组合符号支持嵌套功能。
[root@localhost jiaofan]# echo $(echo 我是一级嵌套:$(echo 我是二级嵌套:))
我是一级嵌套:我是二级嵌套:
|