目录
[6.read 读取控制台输入](#6.read 读取控制台输入)
1.脚本常用执行方式
(1)采用 bash 或 sh + 脚本的相对路径或绝对路径。(不要赋予脚本+x权限)
(2)输入脚本的绝对路径或相对路径执行脚本(必须具有可执行权限+x)。开启一个新的子 shell 进程来执行脚本。脚本在子 shell 中对变量的操作,默认情况下不会影响到父 shell(即执行脚本的当前 shell)环境。
(3)在脚本路径前使用 . 或 source :在当前 shell 环境中执行脚本,脚本中对变量的修改、环境变量的设置等操作,都会影响到当前的 shell 环境。
2.变量
(1)常用系统变量:HOME、PWD、SHELL、USER等。
(2)自定义变量: 一般为小写。
- env:显示当前 shell 进程中定义的环境变量
- set:不仅会显示环境变量,还会显示当前 shell 会话中定义的所有 shell 变量(包括用户自定义的局部变量)
- export:命令用于将局部变量提升为全局变量,使其可以被当前进程的子进程继承。
(3)只读变量:readonly + 变量名=变量值。
(4)撤销变量:unset + 变量名。
(5)特殊变量:
- n:0代表该脚本的名称;1-9代表第1到第9个参数;参数超过9个用{n},如{10}。
- $#:获取所有输入参数的个数。
- $*:把所有参数看成一个整体。
- $@:把每个参数区分对待。
- $?:最后一次执行的命令的返回状态,正确为0。
3.运算符
(1)格式:(())或[] 。(双小括号中可以直接加运算符,如 > , < ,>= ...)
4.条件判断
(1)基本语法:
-
test + 判断语句。
-
判断语句 \]。(方括号两边都要有空格)
-
-eq 等于 -ne 不等于 -lt 小于 -le 小于等于 -gt 大于 -ge 大于等于;如果是字符串之间的比较,可以用 = 或者 !=。
-
多条件判断:判断语句 && 成立 || 不成立 。
5.流程控制
(1)if 判断语句
bash
1.单分支
if [ 条件判断式 ]; then
程序
fi
if [ 条件判断式 ]
then
程序
fi
2.多分支
if [ 条件判断式 ]
then
程序
elif [ 条件判断式 ]
then
程序
else
程序
fi

(2)case 语句
bash
case $变量名 in
"值 1")
如果变量值等于值 1,则执行程序2
;;
"值 2")
如果变量值等于值 2,则执行程序2
;;
...省略其他分支...
*)
如果变量的值都不是以上的值,则执行此程序
;;
esac
注意:
- case 行尾必须为" in ",每一个匹配模式必须以" ) "结束。
- " ;; "表示命令序列结束,相当于 break。
- " *) "表示默认模式,相当于default。

(3)for 循环
bash
1.
for (( 初始值;循环控制条件;变量变化 ))
do
程序
done
2.
for 变量 in 值1 值2 值3...
do
程序
done
(4)while 循环
bash
while [ 条件判断式 ]
do
程序
done

6.read 读取控制台输入
(1)语法:read (选项) (参数)
- -p:指定读取值时的提示信息。
- -t:指定读取值时等待的时间(秒)。
- 参数:指定读取值的变量名。

7.函数
(1)系统函数:
- basename + string/pathname + suffix 。(取路径里的文件名;指定suffix,该命令会将 pathname 或 string 中的 suffix 去掉)
- dirname + 文件绝对路径。(从给定的绝对路径中去除文件名,返回目录的部分)
(2)自定义函数
bash
#基本语法
function funname()
{
Action;
[return int;]
}
- 函数返回值只能通过 $? 系统变量获得。return 后跟数值 n(0-255)。

8.正则表达式
(1)特殊字符:
- ^ 匹配一行的开头。
- 匹配一行的结束。 **\^** 匹配空行。
- . 匹配一个任意的字符。
- * 不单独使用,和上一个字符连用,表示匹配上一个字符 0 次或多次。 .* 匹配任意字符串。
- 字符区间 [ ] 表示匹配某个范围内的一个字符。如:[0-9]*------匹配任意长度的数字字符串。
- \ 表示转义,如:'\$' 。

9.文本处理工具
(1)cut [选项] filename :剪切数据。-f:指定列号;-d:指定分隔符,默认是制表符"\t";-c:按字符进行切割,后面可以加数字表示取第几列。



(2)awk [选项] '/pattern1/{action1} /pattern2/{action2}...' filename:将文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行分析处理。
- pattern:表示 awk 在数据中查找的内容,就是匹配模式。
- action:在找到匹配内容时所执行的一系列命令。
- -F:指定输入文件分割符
- -v:赋值一个用户定义变量。
- BEGIN 在所有数据读取之前执行;END 在所有数据执行之后执行。
- awk 内置变量:FILENAME:文件名;NR:行号;NF:列个数。
如:搜索passwd文件以root关键字开头的所有行,并输出该行的第2列。

搜索passwd文件以root关键字开头的所有行,并输出该行的第1列和第2列,中间用逗号分隔。

搜索passwd文件以 u 开头的所有行,并输出该行的第1列和第2列,中间用逗号分隔,且在所有行前面添加列名" user,shell ",在最后一行添加" end of file "。

读取passwd文件中每行的第 3 个字段(用户 ID),并将其与变量 i
的值(1)相加后输出结果。

统计passwd的文件名,行号,列数。

10.综合应用案例
利用 Linux 自带的 mesg 和 write 工具,向其他用户发送消息。
要求:实现一个向某个用户快速发送消息的脚本,输入用户名作为第一个参数,后面直接跟要发送的消息。脚本需要检测用户是否登录在系统中,是否打开消息功能,以及当前发送消息是否为空。
脚本实现如下:
bash
#!/bin/bash
# 查看用户是否登录
login_user=$(who | grep -i -m 1 $1 | awk '{print $1}')
if [ -z login_user ]
then
echo "$1 不在线!"
echo "脚本退出..."
exit
fi
# 查看用户是否开启消息功能
is_allowed=$(who -T | grep -i -m 1 $1 | awk '{print $2}')
if [ $is_allowed != "+" ]
then
echo "$1 没有开启消息功能!"
echo "脚本退出..."
exit
fi
# 确认是否有消息发送
if [ -z $2 ]
then
echo "没有消息发送!"
echo "脚本退出..."
exit
fi
# 从参数中获取要发送的消息
whole_msg=$(echo $* | cut -d " " -f 2-)
# 获取用户登录的终端
user_terminal=$(who | grep -i -m 1 $1 | awk '{print $2}')
# 写入要发送的消息
echo $whole_msg | write $login_user $user_terminal
if [ $? != 0 ]
then
echo "发送失败!"
else
echo "发送成功!"
fi
exit