shell 编程 实例
案例:
- 字符串截取 ?
使用 ${} 怎么做 截取?
[root@work ~]# SCHOOL="Tarena IT Group."
[root@work ~]# echo ${#SCHOOL}
16
[root@work ~]# echo ${SCHOOL::6}
Tarena
[root@work ~]# echo ${SCHOOL:0:6}
Tarena
[root@work ~]# echo ${SCHOOL:1:6}
arena
[root@work ~]#
使用expr substr 怎么截取?
[root@work ~]# SCHOOL="Tarena IT Group."
[root@work ~]# expr substr "$SCHOOL" 1 6 //必须加引号 注意
Tarena
使用 cut 工具 怎么分隔?
[root@work ~]# SCHOOL="Tarena IT Group."
[root@work ~]# echo $SCHOOL | cut -b 1-6
Tarena
[root@work ~]# echo $SCHOOL | cut -b -6
Tarena
[root@work ~]# echo $SCHOOL | cut -b 8-
IT Group.
[root@work ~]# echo $SCHOOL | cut -b 9
T
字符串怎么 替换?
[root@work ~]# SCHOOL="Tarena IT Group."
[root@work ~]# echo ${SCHOOL/r/XXX}
TaXXXena IT Group.
[root@work ~]# echo ${SCHOOL//r/XXX}
TaXXXena IT GXXXoup.
[root@work ~]# echo ${SCHOOL/$SCHOOL/xxx}
xxx
字符串怎么匹配删除 ?
[root@work ~]# echo $MAIL
/var/spool/mail/root
[root@work ~]# echo ${MAIL#*oo}
l/mail/root
[root@work ~]# echo ${MAIL##*oo}
t
[root@work ~]# echo ${MAIL##*/}
root
[root@work ~]# echo $MAIL
/var/spool/mail/root
[root@work ~]# echo ${MAIL%oo*}
/var/spool/mail/r
[root@work ~]# echo ${MAIL%%oo*}
/var/sp
批量修改当前目录下的文件扩展名 将.doc 改为.txt?
[root@work ~]# more rename.sh
#!/bin/bash
for FILE in *.doc
do
mv $FILE ${FILE%.doc}.txt
done
带参数 $1, $2 如: ./rename.sh .txt .doc
[root@work ~]# more rename.sh
#!/bin/bash
for FILE in *"$1"
do
mv $FILE ${FILE%$1}"$2"
done
:- 取值; := 取值 加赋值 ?
[root@work ~]# echo $SCHOOL
Tarena IT Group
[root@work ~]# echo ${SCHOOL:-Tarena}
Tarena IT Group
[root@work ~]# echo $SCHOOL
Tarena IT Group
[root@work ~]# unset SCHOOL
[root@work ~]# echo ${SCHOOL:-Tarena}
Tarena
[root@work ~]# echo $SCHOOL
[root@work ~]#
//变量值不存在情况
[root@work ~]# echo $SCHOOL
[root@work ~]# echo ${SCHOOL:=Tarean}
Tarean
[root@work ~]# echo $SCHOOL
Tarean
//变量值存在的情况
[root@work ~]# echo $SCHOOL
Tarean
[root@work ~]# echo ${SCHOOL:=Tarena IT Group.}
Tarean
[root@work ~]# echo $SCHOOL
Tarean
从键盘读入一个正整数x, 求从 1到 x 的和; 当用户未输入值时, 为了避免出错,x赋初值1. ?
[root@work ~]# more sumx.sh
#!/bin/bash
read -p "请输入一个正整数:" x
x=${x:-1}
i=1; SUM=0
while [ $i -le $x ]
do
let SUM+=i
let i++
done
echo "从1到$x的总和是:$SUM"
怎么 运算 默认 1+2 中 1,2 是被当为字符串的 怎么 加减乘除运算 ?
[root@work ~]# A=1+2
[root@work ~]# echo $A
1+2
[root@work ~]# X=24
[root@work ~]# A=$X+2
[root@work ~]# echo $A
24+2
[root@work ~]# declare -i A
[root@work ~]# A=1+2
[root@work ~]# echo $A
3
[root@work ~]# declare -i B=$X+2
[root@work ~]# echo $B;
26
//declare -x 可以将局部变量设置为全局变量
// -r 是只读
怎么定义数组, 怎么获取元素, 总数等 ?
[root@work ~]# MY_SVRS=(www ftp mail club)
[root@work ~]# echo ${MY_SVRS[@]}
www ftp mail club
[root@work ~]# echo ${MY_SVRS}
www
[root@work ~]# echo ${MY_SVRS[0]}
www
[root@work ~]# echo ${MY_SVRS[@]:1:2}
ftp mail
[root@work ~]# echo ${#MY_SVRS[@]}
4
怎么 实现 ssh 自动登录脚本 ,主要用到了什么功能?
[root@work ~]# more ./expect_ssh.sh
#!/usr/bin/expect
set host 192.168.3.154
set user root
set password "123qwe"
spawn ssh $user@$host
expect {
"yes/no" {send "yes\r";exp_continue}
"password" {send "123qwe\r"}
}
expect "\[$user\@" { send "pwd >> /tmp/$user.txt; exit\r" }
interact
使用正则表达式 :
[root@work ~]# grep '^root|^daemon' /etc/passwd
[root@work ~]# grep '^root\|^daemon' /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:2:2:daemon:/sbin:/sbin/nologin
[root@work ~]# grep -E '^root|^daemon' /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:2:2:daemon:/sbin:/sbin/nologin
[root@work ~]# egrep '^root|^daemon' /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:2:2:daemon:/sbin:/sbin/nologin
我 只是想判断是否也有复合正则 ,不需要输出 怎么做?
使用 -q ; quiet 静默
[root@work ~]# grep -q '^192.168' /etc/hosts && echo "yes" || echo "no"
怎么输出匹配到的行数?
[root@work ~]# egrep -c '/sbin/nologin$' /etc/passwd
31
[root@work ~]# egrep '/sbin/nologin$' /etc/passwd | wc -l
31
怎么匹配 某个单词?怎么匹配以ll结尾的单词的行 ?
[root@work ~]# egrep '\binit\b' /etc/rc.local
[root@work ~]# egrep '\<init\>' /etc/rc.local
[root@work ~]# egrep 'll\>' /etc/rc.local
[root@work ~]# egrep 'll\b' /etc/rc.local
匹配MAC地址 正则?
- [0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}
邮箱正则?
- [0-9a-zA-Z_.]{3,}@[0-9a-zA-Z.-]{2,}(\.[0-9a-zA-Z-]{2,})+
IP地址正则?
- \<[0-9]{1,3}(\.[0-9]{1,3}){3}\>
sed 命令 实例:
输出 文件第一行?
[root@work ~]# sed -n '1p' /etc/passwd
删除 文件 1-4行文本 ?
[root@work ~]# sed '1,4d' rc.local
//注意不用加 -n
直接 删除原文件 1-4行 文本。?
使用 -i 选项
[root@work ~]# sed -i '1,4d' rc.local
怎么指定多个编辑指令?比如 输出 第一行,第四行内容?
使用 -e 或 ; (分号)
[root@work ~]# sed -n -e '1p' -e '4p' rc.local
[root@work ~]# sed -n '1p;4p' rc.local
[root@work ~]# sed -n '{1p;4p}' rc.local
输出所有行,?相当于 cat命令
[root@work ~]# sed -n 'p' rclocal.txt
输出第 2行及 之后的3行?
[root@work ~]# sed -n '2,+3p' rclocal.txt
输出以 xxx (local) 结尾的 行 ?
[root@work ~]# sed -n '/local$/p' rclocal.txt
输出奇数行?
[root@work ~]# sed -n 'p;n' rclocal.txt
输出偶数行?
[root@work ~]# sed -n 'n;p' rclocal.txt
输出最后一行?
[root@work ~]# sed -n '$p' rclocal.txt
输出文件的 总的行数?
[root@work ~]# sed -n '$=' rclocal.txt
删除 包含 init , bin的行 ?
[root@work ~]# sed '/init/d;/bin/d' rclocal.txt
删除 不包含init 的行 删除 ?
!d
[root@work ~]# sed '/init/ !d' rclocal.txt
p
[root@work ~]# sed -n '/init/p' rclocal.txt
删除所有空行 ?
^$
[root@work ~]# sed '/^$/d' rclocal.txt
替换 s
将 所有行 第一个ll 替换为 “XX” ?
[root@work ~]# sed 's/ll/XX/' rclocal.txt
将 所有行 中 所有 ll 替换为 “XX” ?
[root@work ~]# sed 's/ll/XX/g' rclocal.txt
将第3行内 的 第2个 “script” 替换为 “XX” ?
[root@work ~]# sed '3s/script/XX/2' rclocal.txt
删除 指定的字符串 ?
替换为空
[root@work ~]# sed 's/init//g' rclocal.txt
删除所有的“script” “stuff” 字母 “e” ?
或的关系 要用 \| 来表示
[root@work ~]# sed 's/script\|stuff\|e//g' rclocal.txt
去掉3-5 行的注释?
[root@work ~]# sed '3,5s/^#//' rclocal.txt
将 /etc/rc.local 文件 的第 6-7行 注释掉 ?
行首添加 #
[root@work ~]# sed '6,7s/^/#/' rclocal.txt
将 文件每行 第1 个字符, 第二个字符交换?
-r 启用正则扩展 \2 引用第二个()匹配到的。
[root@work ~]# sed -r 's/^(.)(.)/\2\1/' rclocal.txt
删除行首 空格 ?
[root@work ~]# sed -r 's/^( )+//' rclocal.txt
为文件中每个大些字母添加 括号?
& 代表 匹配到的 整个字符串
[root@work ~]# sed 's/[A-Z]/(&)/g' rclocal.txt
[root@work ~]# sed -r 's/([A-Z])/(\1)/g' rclocal.txt
对网卡 配置文件 eth0 的修改 :
将IP地址 192.168.3.135 修改为 192.168.3.136 ?
思路 首先 定位到 IPADDR (正则定位)
[root@work ~]# sed -i '/IPADDR/s/192.168.3.29/192.168.3.136/' /etc/sysconfig/network-scripts/ifcfg-eth0
sed 的多行操作:
c : 替换指定的行
i :在指定的行之前插入文本
a : 在指定的行 后追加 文本
sed 怎么整行替换呢:?
修改主机名 ?
c : 替换 指定的行
[root@work ~]# sed -i '/^HOSTNAME/cHOSTNAME=liang' /etc/sysconfig/network
在 hosts 文件中, 添加两行记录 (a追加)
[root@work ~]# sed -i '$a192.168.3.200 liang1.com\
> 192.168.3.202 liang2.com' /etc/hosts
综合案例:
找到 使用bash 登录 shell 的本地用户; 按每行 用户名—》 密码 保存到文件a.log中 ?
#!/bin/bash
> /tmp/getupwd.log ##创建空文件
sed -n '/:\/bin\/bash$/w /tmp/user.tmp' /etc/passwd ##提取符合条件的帐号记录
UNUM=$(egrep -c '.' /tmp/user.tmp) ##取得记录个数
#echo $UNUM
while [ ${i:=1} -le $UNUM ]
do
UREC=$(sed -n "${i}p" /tmp/user.tmp)
#echo $UREC
NAME=${UREC%%:*} ##截取用户名:记录去尾
PREC=$(sed -n "/^$NAME:/p" /etc/shadow) ##查找与用户名对应的密码记录
PASS=${PREC#*:} ##掐头
PASS=${PASS%%:*} ##去尾
echo "$NAME--> $PASS" >> /tmp/getupwd.log ##保存结果
let i++
done
/bin/rm -rf /tmp/user.tmp
echo "用户分析完毕,请查看文件/tmp/getupwd.log"
二:使用awk 的方案
#!/bin/bash
> /tmp/getupwd.log
awk -F: '/:\/bin\/bash$/{print $1}' /etc/passwd > /tmp/user.tmp ##提取用户名
for NAME in $(cat /tmp/user.tmp)
do
#grep "^$NAME:" i /etc/shadow | awk -F: '{print $1 "--->" $2}' /etc/shadow
#echo $NAME
grep "^$NAME:" /etc/shadow | awk -F: '{print $1 "--->" $2 | "cat >>/tmp/getupwd.log"}'
done
echo "用户分析完毕,请查看/tmp/getupwd.log"
/bin/rm -rf /tmp/user.tmp
参考 tts-shell day05练习。
awk 实例:
awk 是 怎么指定分隔符 呢?
默认是:不指定 就是 空格 或 制表符 做分隔;
[root@work ~]# awk -F: '{print $1","$7}' /etc/passwd
[root@work ~]# awk -F":" '{print $1","$7}' /etc/passwd
awk 怎么指定多个分隔符呢?
[root@work ~]# awk -F [:/] '{print $1,$10}' /etc/passwd
awk 有哪些内置的变量 ? 当前行号,列数 文件名?
[root@work ~]# awk '{print FILENAME,NR}' /etc/passwd
[root@work ~]# awk -F[:/] '{print NR,NF}' /etc/passwd
awk 怎么使用环境变量? 输出当前用户的passwd的记录?
[root@work ~]# awk -F: '$1==ENVIRON["USER"]{print $0}' /etc/passwd
统计使用bash 作为登录shell 的用户总个数?
思路: 在begin 定义 计数变量 ; \< bash 匹配bash
[root@work ~]# awk 'BEGIN{x=0}/\<bash$/{x++}END{print x}' /etc/passwd
[root@work ~]# egrep -c '\<bash$' /etc/passwd
从ifconfig eth0 提取IP地址?
[root@work ~]# ifconfig eth0 | grep "inet addr:" | awk '{print $2}' | awk -F: '{print $2}'
根分区 使用率?
[root@work ~]# df -hT / | tail -1 | awk '{print $5}'
分析/etc/passwd 文件 输出 列表头; 用户信息,bash信息,, 尾部:行数, 统计信息。
[root@work ~]# awk -F: 'BEGIN{print "User\tUID\tHome"} \
> {print $1"\t"$3"\t"$6} END{print "Total "NR" lines."}' /etc/passwd
输出 其中登录shell 不以nologin结尾 的用户名,登录shell信息?
第七个字段 !~ 反向匹配
[root@work ~]# awk -F: '$7!~/nologin$/{print $1, $7}' /etc/passwd
输出第3行的用户记录?
NR ==3
[root@work ~]# awk -F: 'NR==3{print}' /etc/passwd
输出奇数行的用户记录?
[root@work ~]# awk -F: 'NR%2==1{print}' /etc/passwd
输出偶数行的用户记录?
[root@work ~]# awk -F: 'NR%2==0{print}' /etc/passwd
输出前3行用户记录?
[root@work ~]# awk -F: 'NR<=3{print}' /etc/passwd
输出第3-5 行 用户记录?
[root@work ~]# awk -F: 'NR>=3 && NR<=5{print}' /etc/passwd
输出 登录shell 不以nologin 结尾 或者 用户名 以 a 或d 开头 的文本 ?
[root@work ~]# awk -F: '$7!~/nologin$/||$1~/^[ad]/{print}' /etc/passwd
统计文件中 字段个数 ?
[root@work ~]# awk -F: 'BEGIN{x=0}{x+=NF}END{print "Total "x" fields."}' /etc/passwd
列出100以内 整数中7的倍数 或是含7的数?
[root@work ~]# seq 100 | awk '$0%7==0||$0~/7/{print}'
awk 流程控制考察。
统计/etc/passwd 文件中登录shell不是“/bin/bash” 的用户个数:?
单分支
[root@work ~]# awk -F: 'BEGIN{i=0}{if($7!~/bash$/){i++}}END{print i}' /etc/passwd
统计 /etc/passwd 文件中UID 小于或等于500, UID 大于500的用户个数:?
双分支
[root@work ~]# awk -F: 'BEGIN{i=0;j=0}{if($3<=500){i++}else{j++}}END{print i,j}' /etc/passwd
统计 /etc/passwd 文件中登录shell 是 /bin/bash sbin/nologin ,其他用户 的个数 ?
[root@work ~]# awk -F: 'BEGIN{i=0;j=0;k=0}{if($7~/bash$/){i++}else if($7~/nologin$/){j++}else{k++}}END{print i,j,k}' /etc/passwd
统计 /etc/passwd 文件内 root 出现的次数 ?
[root@work ~]# awk -F [:/] 'BEGIN{j=0}{i=1}{while(i<=NF){if($i~/root/){j++} i++}}END{print j}' /etc/passwd
[root@work ~]# echo $(cat /etc/passwd) | awk -F "root" '{print NF-1}'
计算从1-100内各整数的总和 ?
[root@work ~]# awk 'BEGIN{for(i=1;i<=100;i++){sum += i} print sum}'
[root@work ~]# awk 'BEGIN{for(i=1;i<=100;i++){sum += i; if(i==100){print sum}}}'
[root@work ~]# awk 'BEGIN{for(i=1;i<=100;i++){sum +=i;}}{}END{print sum}' /etc/passwd
跳过 当前 行 ?
next
[root@work ~]# awk 'NF<=2{next}{print}' /etc/rc.local
去处重复的行?
[root@work ~]# awk '!a[$0]++' a1.txt
[root@work ~]# awk '!a[$0]++{print $0}' a1.txt
统计web 访问日志 /var/log/httpd/access_log 统计IP 访问量 ; 按访问量排序?
sort ; //-n 按数字排序 -r反序 ;-k2 按第二列排序
[root@work ~]# awk '{ip[$1]++}END{for(i in ip){print i,ip[i]}}' access.log
[root@work ~]# awk '{ip[$1]++}END{for(i in ip){print i, ip[i]}}' access.log | sort -nr -k2
参考 tts-shell day06练习。