linux实验之shell编程基础

这世间,青山灼灼,星光杳杳,秋风渐渐,晚风慢慢

shell编程基础

    • 熟悉shell编程的有关机制,如标准流。
    • 学习Linux环境变量设置文件及其内容
      • /etc/profile
      • /etc/bashrc
      • /etc/environment
      • ~/.profile
      • ~/.bashrc
    • 熟悉编程有关基础命令技巧和规则
      • awk
          • ( 1 ) 按行输出文本
          • ( 2 )按字段输出文本
      • sed
          • ( 1 ) 输出符合条件的文本
          • ( 2 ) 删除符合条件的文本
          • ( 3 ) 替换符合条件的文本
          • ( 4 ) 迁移符合条件的文本
      • bc
    • 掌握shell 程序执行的三种基本方式,注意调试shell程序的命令书写方式有什么不同?
    • 使用for循环语句编写一段B-shell程序,完成显示用户注册目录下的a_sub, b_sub子目录下的所有C程序文件及其目标文件的列表。
    • 编写一段shell程序完成:根据从键盘输入的学生成绩,显示相应的成绩标准(分出不及格、及格60、中70、良80和优秀90等)。
    • 为便于系统管理员对磁盘分配的管理,请编写一段B-shell程序,当文件系统/home占用空间改变时给出相应的信息提示。要求/home占用量在系统磁盘中为:
    • 假设score.txt文件中保存了三个班级的学生的某门课程考试成绩,请编写一段shell程序计算每个班级的学生人数与平均分。

熟悉shell编程的有关机制,如标准流。

如果当前目录下有文件f1,但是没有f2,解释命令ls f1 f2 2>ef1 1>&2的运行结果。

1 . ls f1 f2 2>ef1 1>&2

(1)

0 表示 stdin , 标准输入 ; 1 表示 stdout , 标准输出 ; 2 表示 strerr , 标准错误输出

1>&2 表示 将标准输出重定向至标准错误输出; 2>&1 表示 将标准错误输出

(2) 所以这里是把ls f1 f2命令的报错信息写入ef1, 又把命令的输出的正常信息当成报错信息写入ef1
linux实验之shell编程基础_第1张图片
如果没有把结果重定向, 就是直接输出
linux实验之shell编程基础_第2张图片

学习Linux环境变量设置文件及其内容

根据实验系统查看/etc/profile,/etc/bashrc,/.bash_profile,/.bashrc等有关文件。

/etc/profile

在系统启动后第一个用户登录时运行,并从/etc/profile.d目录的配置文件中搜集shell的设置,使用该文件配置的环境变量将应用于登录到系统的每一个用户。

/etc/bashrc

(Ubuntu和Debian中是/etc/bash.bashrc)

在 bash shell 打开时运行,修改该文件配置的环境变量将会影响所有用户使用的bash shell。

/etc/environment

在系统启动时运行,用于配置与系统运行相关但与用户无关的环境变量,修改该文件配置的环境变量将影响全局。

~/.profile

当用户登录时执行,每个用户都可以使用该文件来配置专属于自己使用的shell信息。

~/.bashrc

当用户登录时以及每次打开新的shell时该文件都将被读取,不推荐在这里配置用户专用的环境变量,因为每开一个shell,该文件都会被读取一次,效率肯定受影响。

熟悉编程有关基础命令技巧和规则

如变量的命名,引用,位置变量及使用,输出语句及输出格式控制,输入语句和变量存储,从命令输出中提取字段值等。

##熟悉常见外部工具,如awk,sed,bc等的基本用法。

awk

逐行读取输入文本,并根据指定的匹配模式进行查找,对符合条件的内容进行格式化输出或者过滤处理,用于在无交互的情况下实现相当复杂的文本操作。

用法:

1 . 过滤并输出文件中符合条件的内容

awk 选项 ‘模式或条件 {编辑指令}’ 文件 1 文件 2 …

( 1 ) 按行输出文本
awk '{print}' demo.txt	//输出所有内容,等同于 cat demo.txt
awk '{print $0}' demo.txt	//输出所有内容,等同于 cat demo.txt
awk 'NR==1||NR==3{print}' demo.txt	//输出第 1 行、第 3 行内容
awk '(NR>=1)&&(NR<=3){print}' demo.txt	//输出第 1~3 行内容
awk '(NR%2)==1{print}' demo.txt	//输出所有奇数行的内容
awk '(NR%2)==0{print}' demo.txt	//输出所有偶数行的内容
awk '/^root/{print}' /etc/passwd	//输出以root 开头的行awk 
awk '/nologin$/{print}' /etc/passwd	//输出以 nologin 结尾的行
( 2 )按字段输出文本
awk '{print $3}' test.txt	//输出每行中(以空格或制表位分隔)的第 3 个字段
awk '{print $1,$3}' test.txt	//输出每行中的第 1、3 个字段
awk -F ":" '$2==""{print}' /etc/shadow //输出密码为空的用户的shadow 记录
awk 'BEGIN {FS=":"}; $2==""{print}' /etc/shadow  //输出密码为空的用户的shadow 记录
awk -F ":" '$7~"/bash"{print $1}' /etc/passwd  //输出以冒号分隔且第 7 个字段中包含/bash 的行的第 1 个字段
awk '($1~"nfs")&&(NF==8){print $1,$2}' /etc/services   //输出包含 8 个字段且第 1 个字段中包含 nfs 的行的第 1、2 个字段
awk -F ":" '($7!="/bin/bash")&&($7!="/sbin/nologin"){print}' /etc/passwd  //输出第 7 个字段既不为/bin/bash 也不为/sbin/nologin 的所有行     

2 . 从脚本中调用编辑指令,过滤并输出内容

awk -f 脚本文件 文件 1 文件 2 …

awk -F: '/bash$/{print | "wc -l"}' /etc/passwd  //调用wc -l 命令统计使用 bash 的用户个数,等同于 grep -c "bash$" /etc/passwd

awk 'BEGIN {while ("w" | getline) n++ ; {print n-2}}'  //调用w 命令,并用来统计在线用户数

awk 'BEGIN { "hostname" | getline ; print $0}'  //调用hostname,并输出当前的主机名

sed

( 1 ) 输出符合条件的文本
sed -n 'p' demo.txt //输出所有内容
sed -n 'p;n' demo.txt //输出所有奇数行,n表示读入下一行
sed -n 'n;p' demo.txt	//输出所有偶数行,n 表示读入下一行
sed -n '10,${n;p}' demo.txt	//输出第 10 行至文件尾之间的偶数行

sed 命令结合正则表达式时,格式略有不同,正则表达式以“/”包围。

sed -n '/the/p' demo.txt	//输出包含the 的行
sed -n '4,/the/p' demo.txt	//输出从第 4 行至第一个包含 the 的行
sed -n '/^PI/p' demo.txt	//输出以PI 开头的行
sed -n '/[0-9]$/p' demo.txt	//输出以数字结尾的行
sed -n '/\/p' demo.txt   //输出包含单词wood 的行,\<、\>代表单词边界
( 2 ) 删除符合条件的文本
sed '1,3d' 1.txt        #删除第1-3行
sed '/acb/d' 1.txt      #删除所有包含acb的行
sed '/aaa/!d' 1.txt     #删除不包含aaa的行
sed '/^abc/d' 1.txt     #删除以abc开头的行
sed '/\.$/d' demo.txt	//删除以"."结尾的行
sed '/^$/d' demo.txt	//删除所有空行
( 3 ) 替换符合条件的文本
sed 's/the/THE/' demo.txt	   //将每行中的第一个the 替换为 THE
sed 's/l/L/2' demo.txt	       //将每行中的第 2 个 l 替换为 L
sed 's/the/THE/g' demo.txt	     //将文件中的所有the 替换为 THE
sed 's/^/#/' demo.txt	        //在每行行首插入#号
sed '/the/s/^/#/' demo.txt	   //在包含the 的每行行首插入#号
sed '/the/s/o/O/g' demo.txt	//将包含the 的所有行中的 o 都替换为 O
sed '3,5s/the/THE/g' demo.txt   //将第3~5行中所有the替换为 THE
sed 's/$/NO/' demo.txt	       //在每行行尾插入字符串NO
( 4 ) 迁移符合条件的文本

在使用 sed 命令迁移符合条件的文本时,常用到以下参数.

  • H:复制到剪贴板。
  • g、G:将剪贴板中的数据覆盖/追加至指定行。
  • w:保存为文件。
  • r:读取指定文件。
  • a:追加指定内容。
sed '/the/{H;d};$G' test.txt	//将包含the 的行迁移至文件末尾,{;}用于多个操作

sed '1,5{H;d};17G' test.txt	//将第 1~5 行内容转移至第 17 行后
sed '/the/w out.file' test.txt	//将包含the 的行另存为文件 out.file

sed '/the/r /etc/hostname' test.txt	//将文件/etc/hostname 的内容添加到包含 the 的每行以后

sed '3aNew' test.txt	//在第 3 行后插入一个新行,内容为New
sed '/the/aNew' test.txt	//在包含the 的每行后插入一个新行,内容为 New

sed '3aNew1\nNew2' test.txt	//在第 3 行后插入多行内容,中间的\n 表示换行

sed '1,5{H;d};17G' test.txt	//将第 1~5 行内容转移至第 17 行后

bc

  • +:加
  • -:减
  • *:乘
  • /:除
  • ^:指数
  • %:求余数
  • sqrt:开方
  • ibase:输入进制
  • obase:输出进制
  • ;要计算多个结果用分号分隔
  • scale:小数部分位数

比如:

  • 3除以2保留3位小数:echo ‘scale=3; 3/2’ | bc

  • 10进制的3转换为2进制:echo “obase=2;3” |bc

  • 10进制的11转换为16进制:echo “obase=16;11” |bc

  • 2进制转16进制:echo “obase=16;ibase=2;11” |bc

  • 2进制转10进制:echo “obase=10;ibase=2;11” |bc

  • 100开方: echo “sqrt(100)” |bc

  • 10的3次方,10的2次方,3的5次方: echo “103;102;3^5” |bc

掌握shell 程序执行的三种基本方式,注意调试shell程序的命令书写方式有什么不同?

(1)输入重定向的执行方式

Shell从文件test中读取命令行并执行它们,
Shell执行到文件末尾就会终止执行

sh < test.sh

(2)脚本名文件执行
可以将参数值传递给文件中的命令,使shell程序可以处理更多的情况

sh test.sh [参数.]

(3)添加执行权限,直接进行执行

chmod u+x test.sh
./test.sh

(4)调试shell程序的命令
linux实验之shell编程基础_第3张图片
在脚本头部添加

set -euxo pipefail

linux实验之shell编程基础_第4张图片
或执行时传⼊参数

bash -euxo pipefail xxx.sh

linux实验之shell编程基础_第5张图片

使用for循环语句编写一段B-shell程序,完成显示用户注册目录下的a_sub, b_sub子目录下的所有C程序文件及其目标文件的列表。

考虑如何验证实验结果。

用户注册目录: $HOME查看
linux实验之shell编程基础_第6张图片

#!/bin/bash
d="$HOME/a_sub $HOME/b_sub"     #找到这两个目录
for i in $d
do
    cd $i                       #然后进入目录
    ls -l *.c                   #分别输出
done

linux实验之shell编程基础_第7张图片

编写一段shell程序完成:根据从键盘输入的学生成绩,显示相应的成绩标准(分出不及格、及格60、中70、良80和优秀90等)。

如果输入的数据不是合法的怎么处理?

11.sh

#!/bin/bash
while :
do  
  read -p "输入成绩:" s
  case "$s" in
  q|Q)
      exit
      ;;
  *)
    
      if ! [[ "$s" =~ ^[0-9]+$ ]] ; then 
         echo "请输入数字"
         continue
      fi
      
      if [ $s -ge 90 -a $s -le 99 ] ; then
         echo "优秀"
      fi
      
      if [ $s -ge 80 -a $s -le 89 ] ; then
         echo "良"
      fi
      
      if [ $s -ge 70 -a $s -le 79 ] ; then
         echo "中"
      fi
      
      if [ $s -ge 60 -a $s -le 69 ] ; then
         echo "及格"
      fi
      
      if [ $s -ge 0 -a $s -le 59 ] ; then
         echo "不及格"
      fi

      ;;
  esac
done 

linux实验之shell编程基础_第8张图片

为便于系统管理员对磁盘分配的管理,请编写一段B-shell程序,当文件系统/home占用空间改变时给出相应的信息提示。要求/home占用量在系统磁盘中为:

①小于50%时,提示“用户文件系统磁盘使用负荷量小”。

②大于50%,小于90%时,提示“用户文件系统磁盘使用负荷量正常”。

③大于等于90%时,提示“用户文件系统磁盘使用负荷量偏大。

思路:怎么获取磁盘的空间情况?注意题目是需要知道一个目录的空间占用情况,和磁盘的占用不是一个问题。

df -h /home > homespace1.txt

单独运行df和du命令,查看用户注册目录的空间使用情况,然后再根据此二命令的输出,决定编程的方法。
linux实验之shell编程基础_第9张图片

#!/bin/bash
df -h /home > homespace1.txt
#将/home目录占用磁盘空间的情况输出重定向到一个txt文件中去

s=`sed -n '2p' homespace1.txt`
#把homespace.txt文件里的第二行赋值给temp变量
#sed命令是利用脚本来处理文件
#-n:仅显示script处理后的结果
l=${s%'%'*}
#从右往左,把第一次出现%的右边截掉,保留左边,因为%符号有特殊含义,所以加上单引号'%',把截取后的字符串片段先赋值给m变量
r=${l##*G}

#从左往右,把字符串最后一个出现字符G的左边截掉,保留右边。这样就把占用空间百分比的数字给截取出来了,把它赋值给r变量
for i in $r
do
    if [ $i -le 50 ] ; then
        echo "用户文件系统磁盘使用负荷量小"
    fi    

    if [ $i -ge 50 -a $i -le 90 ] ; then
        echo "用户文件系统磁盘使用负荷量正常"
    fi    

    if [ $i -ge 90 ] ; then
        echo "用户文件系统磁盘使用负荷量偏大"
    fi
done


linux实验之shell编程基础_第10张图片

假设score.txt文件中保存了三个班级的学生的某门课程考试成绩,请编写一段shell程序计算每个班级的学生人数与平均分。

学习读取文件的方法。

linux实验之shell编程基础_第11张图片

#!/bin/bash

class="class1 class2 class3"
for i in $class
do
	total=`grep -F $i score.txt|wc -l`
	
	average=`grep -F $i score.txt|awk -F: '{sum+=$3}END{print ":",sum/NR}'`
	#在之前检索出来的一个班级的内容中截取第三列所在的内容,并进行累加得到sum,sum再除以内置变量NR(行数)就得到平均值了。
	
	echo "$i班:$total人,平均分$average。"
done

如果数据文件的内容是3个班级5门不同课程的内容,程序应该怎么调整?

#!/bin/bash

class="class1 class2 class3"
for i in $class
do
	total=`grep -F $i score1.txt|wc -l`
	echo "$i班:$total人"
	for j in 2 3 4 5 6 7
	do
		x=`sed -n '1p' score1.txt|awk -F" " '{print $'$j'}'`
		#获取第一行的内容,读取科目,便于简化操作。
		average=`grep -F $i score1.txt|awk -F" " '{sum+=$'$j'}END{print sum/NR}'`
		echo "$i$x平均分:$average"
	done
done

你可能感兴趣的:(linux实验,linux,bash,运维)