sed命令,until语句,case语句(第15天)
回顾:selinux, while语句
selinux: 内核,安全加强;
开启selinux可以使用配置文件或者setenforce和getenforce这组命令:
selinux的配置文件:/etc/sysconfig/selinux, /etc/selinux/config
# setenforce和getenforce命令用于设置和查看
打标签:
chcon [-t TYPE]
-R
布尔型:
getsebool [-a]
setsebool [-P]
sed:编辑器
sed: Stream EDitor, 文本流编辑器,行编辑器,逐行处理;
sed工作原理:
sed把文件中的地址界定的内容逐行取出放入模式空间中编辑,编辑完成之后,最后将编辑完的结果输出到屏幕中。
用法如下:
sed [option]... 'script' inputfile...
script: script表示脚本,由2部分组成,分别是地址定界加编辑命令
例如 sed [option]... "地址定界编辑命令;地址定界编辑命令" /etc/fstab/
常用选项:
-n:不输出模式中的内容至屏幕;
-e: 多点编辑;
-f /PATH/TO/SCRIPT_FILE: 从指定文件中读取编辑脚本;
-r: 支持使用扩展的正则表达式;
-i: 原处编辑;
地址定界:
(1) 不给地址:对全文进行处理;
(2) 单地址:
#: 指定的行;其中 $表示最后一行,类似的$-1就表示倒数第二行
/pattern/:被此处模式所能够匹配到的每一行;
(3) 地址范围:
#,#
#,+#
/pat1/,/pat2/
#,/pat1/
(4) ~:步进
1~2
2~2
编辑命令:
d: 删除
p: 显示模式空间中的内容 例子 sed -n "/^UUID/p" /etc/fstab
a \text:在行后面追加文本;支持使用\n实现多行追加;
例如 sed "/^UUID/a \test append" /etc/fstab
i \text:在行前面插入文本;支持使用\n实现多行插入;
例如 sed "/^UUID/i \test insert" /etc/fstab
c \text:替换行为单行或多行文本;
例如 sed "/^UUID/c \change" /etc/fstab
w /path/to/somefile: 保存模式空间匹配到的行至指定文件中;
例如 sed "/^UUID/w /tmp/uuid.txt" /etc/fstab
r /path/from/somefile:读取指定文件的文本流至模式空间中匹配到的每一行的行后;
例如 sed "/^UUID/r /etc/issue" /etc/fstab
=: 为模式空间中的行打印行号;
!: 取反条件;
例如 sed "/^UUID/!d" /etc/fstab
s/模式/替换内容/:查找替换命令,支持使用其它分隔符,s@@@,s###;替换内容不能使用模式,但可以使用\1, \2, ...等后向引用符号;还可以使用“&”引用前面查找时查找到的整个内容。
替换标记有g,p,w:
g: 行内全局替换;
p: 显示替换成功的行;
w /PATH/TO/SOMEFILE:将替换成功的结果保存至指定文件中;
例如 sed "s/^UUID/uuid/g" /etc/fstab
sed -n "s/r..t/&er/pg" /etc/passwd
练习1:删除/boot/grub/grub.conf文件中所有以空白开头的行行首的空白字符;
~]# sed 's@^[[:space:]]\+@@' /etc/grub2.cfg
练习2:删除/etc/fstab文件中所有以#开头,后面至少跟一个空白字符的行的行首的#和空白字符;
~]# sed "s/^#[[:space:]]\+//" /etc/fstab
练习3:echo一个绝对路径给sed命令,取出其基名;取出其目录名;
~]# echo "/etc/sysconfig/ll.txt" | sed 's@[^/]\+/\?$@@' 取基名
高级编辑命令:
高级命令中大部分引入了保持空间,sed的保持空间保存未编辑结束的内容。
h: 把模式空间中的内容覆盖至保持空间中;
H:把模式空间中的内容追加至保持空间中;
g: 从保持空间取出数据覆盖至模式空间;
G:从保持空间取出内容追加至模式空间;
x: 把模式空间中的内容与保持空间中的内容进行互换;
n: 读取匹配到的行的下一行至模式空间;
N:追加匹配到的行的下一行至模式空间;
d: 删除模式空间中的行;
D:删除多行模式空间中的所有行;
如果sed需要使用多个地址界定+编辑命令或高级命令,可以用分号隔开。
例子:
sed -n 'n;p' FILE 显示偶数行
sed '1!G;h;$!d' FILE:逆向显示文件内容
分析的时候,一行一行的分析,第一行要经过1!G,h,$!d三阶段分析,然后查看模式空间和保持空间中的数据内容,以此类推,第2行,第3行,... 最后一行,都是如此分析。
sed '$!N;$!D' FILE: 取出文件后两行;
sed '$!d' FILE:取出文件最后一行;
sed 'G' FILE: 每一行后面追加一行空白行
sed '/^$/d;G' FILE:
sed 'n;d' FILE: 显示奇数行;
sed -n '1!G;h;$p' FILE: 逆向显示文件中的每一行;
bash脚本编程
while CONDITION; do
循环体
done
进入条件:CONDITION为true;
退出条件:false
until CONDITION; do
循环体
done
进入条件:false
退出条件:true
示例:求100以内所正整数之和;
#!/bin/bash
#
declare -i i=1
declare -i sum=0
until [ $i -gt 100 ]; do #条件为假时,进入循环
let sum+=$i
let i++
done
echo "Sum: $sum"
示例:打印九九乘法表
#!/bin/bash
#
declare -i j=1
declare -i i=1
until [ $j -gt 9 ]; do
until [ $i -gt $j ]; do
echo -n -e "${i}X${j}=$[$i*$j]\t"
let i++
done
echo
let i=1
let j++
done
循环控制语句(用于循环体中):有continue和break
continue [N]:提前结束第N层的本轮循环,而直接进入下一轮判断;
while CONDTIITON1; do
CMD1
...
if CONDITION2; then
continue
fi
CMDn
...
done
break [N]:提前结束循环;
while CONDTIITON1; do
CMD1
...
if CONDITION2; then
break
fi
CMDn
...
done
示例1:求100以内所有偶数之和;要求循环遍历100以内的所正整数;
#!/bin/bash
#
declare -i i=0
declare -i sum=0
until [ $i -gt 100 ]; do
let i++
if [ $[$i%2] -eq 1 ]; then #如果i是奇数,则不将i加入到sum中。
continue
fi
let sum+=$i
done
echo "Even sum: $sum"
创建死循环:
while true; do
循环体
done
until false; do
循环体
done
示例2:每隔3秒钟到系统上获取已经登录的用户的信息;如果docker登录了,则记录于日志中,并退出;
#!/bin/bash
#
read -p "Enter a user name: " username
while true; do
if who | grep "^$username" &> /dev/null; then
break
fi
echo "will sleep 3 seconds....."
sleep 3
done
echo "$username logged on." >> /tmp/user.log
第二种实现:
#!/bin/bash
#
read -p "Enter a user name: " username
until who | grep "^$username" &> /dev/null; do
echo "will sleep 3 seconds....."
sleep 3
done
echo "$username logged on." >> /tmp/user.log
while循环的特殊用法(遍历文件的每一行):
练习:写一个脚本,完成如下要求
(1) 脚本可接受参数:start, stop, restart, status;
(2) 如果参数非此四者之一,提示使用格式后报错退出;
(3) 如果是start:则创建/var/lock/subsys/SCRIPT_NAME, 并显示“启动成功”;
考虑:如果事先已经启动过一次,该如何处理?
(4) 如果是stop:则删除/var/lock/subsys/SCRIPT_NAME, 并显示“停止完成”;
考虑:如果事先已然停止过了,该如何处理?
(5) 如果是restart,则先stop, 再start;
考虑:如果本来没有start,如何处理?
(6) 如果是status, 则
如果/var/lock/subsys/SCRIPT_NAME文件存在,则显示“SCRIPT_NAME is running...”;
如果/var/lock/subsys/SCRIPT_NAME文件不存在,则显示“SCRIPT_NAME is stopped...”;
其中:SCRIPT_NAME为当前脚本名;
#!/bin/bash
if [ $# -lt 1 ];then
echo "at least one arg"
exit 1
fi
if [ "$1" != 'start' -a "$1" != 'stop' -a "$1" != 'status' -a "$1" != 'restart' ];then
echo "usage:service start|stop|status|restart"
exit 2
fi
service_name=`basename $0 | cut -d'.' -f1`
case $1 in
start)
# echo "$service_name start"
if [ -e /var/lock/subsys/$service_name ];then
echo "$service_name has already start"
else
touch /var/lock/subsys/$service_name
echo "start $service_name success...."
fi
;;
stop)
# echo "$service_name stop"
if [ -e /var/lock/subsys/$service_name ];then
rm -rf /var/lock/subsys/$service_name
echo "stop $service_name success...."
else
echo "$service_name has not start"
fi
;;
status)
# echo "$service_name status"
if [ -e /var/lock/subsys/$service_name ];then
echo "$service_name is running...."
else
echo "$service_name is stoped"
fi
;;
restart)
# echo "$service_name restart"
if [ -e /var/lock/subsys/$service_name ];then
echo "$service_name now is stoppting...."
rm -rf /var/lock/subsys/$service_name
echo "$service_name now is stopped"
echo "$service_name now is restarting...."
sleep 3
touch /var/lock/subsys/$service_name
echo "$service_name now is restart success...."
else
touch /var/lock/subsys/$service_name
echo "$service_name now is restart success...."
fi
;;
esac
selinux: 内核,安全加强;
开启selinux可以使用配置文件或者setenforce和getenforce这组命令:
selinux的配置文件:/etc/sysconfig/selinux, /etc/selinux/config
# setenforce和getenforce命令用于设置和查看
打标签:
chcon [-t TYPE]
-R
布尔型:
getsebool [-a]
setsebool [-P]
sed:编辑器
sed: Stream EDitor, 文本流编辑器,行编辑器,逐行处理;
sed工作原理:
sed把文件中的地址界定的内容逐行取出放入模式空间中编辑,编辑完成之后,最后将编辑完的结果输出到屏幕中。
用法如下:
sed [option]... 'script' inputfile...
script: script表示脚本,由2部分组成,分别是地址定界加编辑命令
例如 sed [option]... "地址定界编辑命令;地址定界编辑命令" /etc/fstab/
常用选项:
-n:不输出模式中的内容至屏幕;
-e: 多点编辑;
-f /PATH/TO/SCRIPT_FILE: 从指定文件中读取编辑脚本;
-r: 支持使用扩展的正则表达式;
-i: 原处编辑;
地址定界:
(1) 不给地址:对全文进行处理;
(2) 单地址:
#: 指定的行;其中 $表示最后一行,类似的$-1就表示倒数第二行
/pattern/:被此处模式所能够匹配到的每一行;
(3) 地址范围:
#,#
#,+#
/pat1/,/pat2/
#,/pat1/
(4) ~:步进
1~2
2~2
编辑命令:
d: 删除
p: 显示模式空间中的内容 例子 sed -n "/^UUID/p" /etc/fstab
a \text:在行后面追加文本;支持使用\n实现多行追加;
例如 sed "/^UUID/a \test append" /etc/fstab
i \text:在行前面插入文本;支持使用\n实现多行插入;
例如 sed "/^UUID/i \test insert" /etc/fstab
c \text:替换行为单行或多行文本;
例如 sed "/^UUID/c \change" /etc/fstab
w /path/to/somefile: 保存模式空间匹配到的行至指定文件中;
例如 sed "/^UUID/w /tmp/uuid.txt" /etc/fstab
r /path/from/somefile:读取指定文件的文本流至模式空间中匹配到的每一行的行后;
例如 sed "/^UUID/r /etc/issue" /etc/fstab
=: 为模式空间中的行打印行号;
!: 取反条件;
例如 sed "/^UUID/!d" /etc/fstab
s/模式/替换内容/:查找替换命令,支持使用其它分隔符,s@@@,s###;替换内容不能使用模式,但可以使用\1, \2, ...等后向引用符号;还可以使用“&”引用前面查找时查找到的整个内容。
替换标记有g,p,w:
g: 行内全局替换;
p: 显示替换成功的行;
w /PATH/TO/SOMEFILE:将替换成功的结果保存至指定文件中;
例如 sed "s/^UUID/uuid/g" /etc/fstab
sed -n "s/r..t/&er/pg" /etc/passwd
练习1:删除/boot/grub/grub.conf文件中所有以空白开头的行行首的空白字符;
~]# sed 's@^[[:space:]]\+@@' /etc/grub2.cfg
练习2:删除/etc/fstab文件中所有以#开头,后面至少跟一个空白字符的行的行首的#和空白字符;
~]# sed "s/^#[[:space:]]\+//" /etc/fstab
练习3:echo一个绝对路径给sed命令,取出其基名;取出其目录名;
~]# echo "/etc/sysconfig/ll.txt" | sed 's@[^/]\+/\?$@@' 取基名
高级编辑命令:
高级命令中大部分引入了保持空间,sed的保持空间保存未编辑结束的内容。
h: 把模式空间中的内容覆盖至保持空间中;
H:把模式空间中的内容追加至保持空间中;
g: 从保持空间取出数据覆盖至模式空间;
G:从保持空间取出内容追加至模式空间;
x: 把模式空间中的内容与保持空间中的内容进行互换;
n: 读取匹配到的行的下一行至模式空间;
N:追加匹配到的行的下一行至模式空间;
d: 删除模式空间中的行;
D:删除多行模式空间中的所有行;
如果sed需要使用多个地址界定+编辑命令或高级命令,可以用分号隔开。
例子:
sed -n 'n;p' FILE 显示偶数行
sed '1!G;h;$!d' FILE:逆向显示文件内容
分析的时候,一行一行的分析,第一行要经过1!G,h,$!d三阶段分析,然后查看模式空间和保持空间中的数据内容,以此类推,第2行,第3行,... 最后一行,都是如此分析。
sed '$!N;$!D' FILE: 取出文件后两行;
sed '$!d' FILE:取出文件最后一行;
sed 'G' FILE: 每一行后面追加一行空白行
sed '/^$/d;G' FILE:
sed 'n;d' FILE: 显示奇数行;
sed -n '1!G;h;$p' FILE: 逆向显示文件中的每一行;
bash脚本编程
while CONDITION; do
循环体
done
进入条件:CONDITION为true;
退出条件:false
until CONDITION; do
循环体
done
进入条件:false
退出条件:true
示例:求100以内所正整数之和;
#!/bin/bash
#
declare -i i=1
declare -i sum=0
until [ $i -gt 100 ]; do #条件为假时,进入循环
let sum+=$i
let i++
done
echo "Sum: $sum"
示例:打印九九乘法表
#!/bin/bash
#
declare -i j=1
declare -i i=1
until [ $j -gt 9 ]; do
until [ $i -gt $j ]; do
echo -n -e "${i}X${j}=$[$i*$j]\t"
let i++
done
echo
let i=1
let j++
done
循环控制语句(用于循环体中):有continue和break
continue [N]:提前结束第N层的本轮循环,而直接进入下一轮判断;
while CONDTIITON1; do
CMD1
...
if CONDITION2; then
continue
fi
CMDn
...
done
break [N]:提前结束循环;
while CONDTIITON1; do
CMD1
...
if CONDITION2; then
break
fi
CMDn
...
done
示例1:求100以内所有偶数之和;要求循环遍历100以内的所正整数;
#!/bin/bash
#
declare -i i=0
declare -i sum=0
until [ $i -gt 100 ]; do
let i++
if [ $[$i%2] -eq 1 ]; then #如果i是奇数,则不将i加入到sum中。
continue
fi
let sum+=$i
done
echo "Even sum: $sum"
创建死循环:
while true; do
循环体
done
until false; do
循环体
done
示例2:每隔3秒钟到系统上获取已经登录的用户的信息;如果docker登录了,则记录于日志中,并退出;
#!/bin/bash
#
read -p "Enter a user name: " username
while true; do
if who | grep "^$username" &> /dev/null; then
break
fi
echo "will sleep 3 seconds....."
sleep 3
done
echo "$username logged on." >> /tmp/user.log
第二种实现:
#!/bin/bash
#
read -p "Enter a user name: " username
until who | grep "^$username" &> /dev/null; do
echo "will sleep 3 seconds....."
sleep 3
done
echo "$username logged on." >> /tmp/user.log
while循环的特殊用法(遍历文件的每一行):
while read line; do
循环体
done < /PATH/FROM/SOMEFILE
依次读取/PATH/FROM/SOMEFILE文件中的每一行,且将行赋值给变量line:
示例:找出其ID号为偶数的所有用户,显示其用户名及ID号;
#!/bin/bash
while read line;do
if [ $[`echo $line | cut -d: -f3` % 2] -eq 0 ];then
echo -e -n "username: `echo $line | cut -d: -f1`\t"
echo "uid: `echo $line | cut -d: -f3 `"
fi
done < /etc/passwd
for循环的特殊格式:
for ((控制变量初始化;条件判断表达式;控制变量的修正表达式)); do
循环体
done
控制变量初始化:仅在运行到循环代码段时执行一次;
控制变量的修正表达式:每轮循环结束会先进行控制变量修正运算,而后再做条件判断;
示例:求100以内所正整数之和;
#!/bin/bash
#
declare -i sum=0
for ((i=1;i<=100;i++)); do
let sum+=$i
done
echo "Sum: $sum."
示例2:打印九九乘法表;
#!/bin/bash
#
for((j=1;j<=9;j++));do
for((i=1;i<=j;i++))do
echo -e -n "${i}X${j}=$[$i*$j]\t"
done
echo
done
控制变量的修正表达式:每轮循环结束会先进行控制变量修正运算,而后再做条件判断;
示例:求100以内所正整数之和;
#!/bin/bash
#
declare -i sum=0
for ((i=1;i<=100;i++)); do
let sum+=$i
done
echo "Sum: $sum."
示例2:打印九九乘法表;
#!/bin/bash
#
for((j=1;j<=9;j++));do
for((i=1;i<=j;i++))do
echo -e -n "${i}X${j}=$[$i*$j]\t"
done
echo
done
练习:写一个脚本,完成如下任务
(1) 显示一个如下菜单:
cpu) show cpu information;
mem) show memory information;
disk) show disk information;
quit) quit
(2) 提示用户选择选项;
(3) 显示用户选择的内容;
#!/bin/bash
#
cat << EOF
cpu) show cpu information;
mem) show memory information;
disk) show disk information;
quit) quit
============================
EOF
read -p "Enter a option: " option
while [ "$option" != 'cpu' -a "$option" != 'mem' -a "$option" != 'disk' -a "$option" != 'quit' ]; do
read -p "Wrong option, Enter again: " option
done
if [ "$option" == 'cpu' ]; then
lscpu
elif [ "$option" == 'mem' ]; then
cat /proc/meminfo
elif [ "$option" == 'disk' ]; then
fdisk -l
else
echo "Quit"
exit 0
fi
进一步地:用户选择,并显示完成后不退出脚本;而是提示用户继续选择显示其它内容;直到使用quit方始退出;
(1) 显示一个如下菜单:
cpu) show cpu information;
mem) show memory information;
disk) show disk information;
quit) quit
(2) 提示用户选择选项;
(3) 显示用户选择的内容;
#!/bin/bash
#
cat << EOF
cpu) show cpu information;
mem) show memory information;
disk) show disk information;
quit) quit
============================
EOF
read -p "Enter a option: " option
while [ "$option" != 'cpu' -a "$option" != 'mem' -a "$option" != 'disk' -a "$option" != 'quit' ]; do
read -p "Wrong option, Enter again: " option
done
if [ "$option" == 'cpu' ]; then
lscpu
elif [ "$option" == 'mem' ]; then
cat /proc/meminfo
elif [ "$option" == 'disk' ]; then
fdisk -l
else
echo "Quit"
exit 0
fi
进一步地:用户选择,并显示完成后不退出脚本;而是提示用户继续选择显示其它内容;直到使用quit方始退出;
条件判断:case语句
case 变量引用 in
PAT1)
分支1
;;
PAT2)
分支2
;;
...
*)
默认分支
;;
esac
case 变量引用 in
PAT1)
分支1
;;
PAT2)
分支2
;;
...
*)
默认分支
;;
esac
示例:
#!/bin/bash
#
cat << EOF
cpu) show cpu information;
mem) show memory information;
disk) show disk information;
quit) quit
============================
EOF
read -p "Enter a option: " option
while [ "$option" != 'cpu' -a "$option" != 'mem' -a "$option" != 'disk' -a "$option" != 'quit' ]; do
read -p "Wrong option, Enter again: " option
done
case $option in
cpu)
lscpu ;;
mem)
cat /proc/meminfo ;;
disk)
fdisk -l ;;
*)
echo "quit....."
exit 0
esac
#!/bin/bash
#
cat << EOF
cpu) show cpu information;
mem) show memory information;
disk) show disk information;
quit) quit
============================
EOF
read -p "Enter a option: " option
while [ "$option" != 'cpu' -a "$option" != 'mem' -a "$option" != 'disk' -a "$option" != 'quit' ]; do
read -p "Wrong option, Enter again: " option
done
case $option in
cpu)
lscpu ;;
mem)
cat /proc/meminfo ;;
disk)
fdisk -l ;;
*)
echo "quit....."
exit 0
esac
练习:写一个脚本,完成如下要求
(1) 脚本可接受参数:start, stop, restart, status;
(2) 如果参数非此四者之一,提示使用格式后报错退出;
(3) 如果是start:则创建/var/lock/subsys/SCRIPT_NAME, 并显示“启动成功”;
考虑:如果事先已经启动过一次,该如何处理?
(4) 如果是stop:则删除/var/lock/subsys/SCRIPT_NAME, 并显示“停止完成”;
考虑:如果事先已然停止过了,该如何处理?
(5) 如果是restart,则先stop, 再start;
考虑:如果本来没有start,如何处理?
(6) 如果是status, 则
如果/var/lock/subsys/SCRIPT_NAME文件存在,则显示“SCRIPT_NAME is running...”;
如果/var/lock/subsys/SCRIPT_NAME文件不存在,则显示“SCRIPT_NAME is stopped...”;
其中:SCRIPT_NAME为当前脚本名;
#!/bin/bash
if [ $# -lt 1 ];then
echo "at least one arg"
exit 1
fi
if [ "$1" != 'start' -a "$1" != 'stop' -a "$1" != 'status' -a "$1" != 'restart' ];then
echo "usage:service start|stop|status|restart"
exit 2
fi
service_name=`basename $0 | cut -d'.' -f1`
case $1 in
start)
# echo "$service_name start"
if [ -e /var/lock/subsys/$service_name ];then
echo "$service_name has already start"
else
touch /var/lock/subsys/$service_name
echo "start $service_name success...."
fi
;;
stop)
# echo "$service_name stop"
if [ -e /var/lock/subsys/$service_name ];then
rm -rf /var/lock/subsys/$service_name
echo "stop $service_name success...."
else
echo "$service_name has not start"
fi
;;
status)
# echo "$service_name status"
if [ -e /var/lock/subsys/$service_name ];then
echo "$service_name is running...."
else
echo "$service_name is stoped"
fi
;;
restart)
# echo "$service_name restart"
if [ -e /var/lock/subsys/$service_name ];then
echo "$service_name now is stoppting...."
rm -rf /var/lock/subsys/$service_name
echo "$service_name now is stopped"
echo "$service_name now is restarting...."
sleep 3
touch /var/lock/subsys/$service_name
echo "$service_name now is restart success...."
else
touch /var/lock/subsys/$service_name
echo "$service_name now is restart success...."
fi
;;
esac
评论
发表评论