linux下shell编程总结
来源:互联网 发布:神笔获取宝贝数据失败 编辑:程序博客网 时间:2024/05/18 00:53
概念
shell是一种弱类型、解释型语言,不需要编译,只需要一个解释器,这里我们用bash。
输入如下命令:
more /etc/passwd
可以看到:
当前用户root登录的时候,默认打开的命令行用户接口就是bash,在这个bash中输入bash又会打开一个子bash接口,可以不断深入的嵌套bash,当然执行退出命令exit时,也会一层一层退出之前打开的bash。
变量类型
环境变量 当前的shell和其子shell
export 名字=值
输入如下命令可以看到环境变量:tail -n 5 /etc/profile
脚本在执行时都会启动一个子shell进程:
命令行中启动的脚本会继承当前shell环境变量。
系统自动启动脚本(非命令行启动):则需要自我定义环境变量。本地变量 作用于当前bash
var_name=值位置变量 用于 脚本执行的参数,$1 表示第一个参数,以此类推$1,$2….记录参数的位置
特殊变量 bash内置的用来保存某些特殊数据的变量。(也叫系统变量)
$? 上一个命令的执行状态返回值。
在之后shell编程中很多情况下我们只需要命令的执行状态,不需要执行结果,所以要让执行结果不在控制台正常输出,这时候需要把命令结果输出重定向。
输入命令:
ls -l /usr
这时候显示结果:
现在我们要把这些命令的执行结果重定向到另一个地方,不在控制台显示:
命令执行正确的结果:
>覆盖重定向 覆盖原有内容>> 追加重定向 在原有内容后追加
命令执行的错误结果:
2> 错误覆盖重定向2>>错误追加重定向
&> 全部重定向 包括正确和错误的结果
这里要介绍一个shell编程中经常用到的重定向语句:
ls /usr &> /dev/null
null是一个设备文件,是一个字符输出设备:
这个字符输出设备有一个特点就是把数据重定向给他之后就再也找不回来了,相当于windows中的垃圾回收站,也叫数据黑洞。
- $# 传递到脚本的参数个数
- $* 传递到脚本的参数,与位置变量不同,此选项参数可超过9个
- $$ 脚本运行时当前进程的ID号,常用作临时变量的后缀,如 haison.$$
- $! 后台运行的(&)最后一个进程的ID号
- $@ 与$#相同,使用时加引号,并在引号中返回参数个数
- $- 上一个命令的最后一个参数
- $? 最后命令的退出状态,0表示没有错误,其他任何值表明有错误
查看变量:
set//可以查看当前bash下的所有变量
printenv//查看所有环境变量
变量的使用
${变量名},一般可以省略{},但不是所有情况都可以省略
自定义变量A=1
直接输出变量A的时候可以省略,但是当我们想输出变量再加一个字符串的时候,发现没有输出任何结果,原因是bash把Aa当成了一个变量,这个时候就需要{}来区分变量和常量字符串。
在bash中 通常有如下替换:
- 单引号:强引用,不做任何处理,只是把其中的值当做字符串
- 双引号:弱引用,做变量替换
- 反引号:“命令替换
脚本编写
创建后缀为.sh的文件(没有后缀也可以)
第一行必须写:
#!/bin/bash //只能放第一行,称之为魔数
由于其起始的几个字节的内容是固定的(或是有意填充,或是本就如此)。根据这几个字节的内容就可以确定文件类型,因此这几个字节的内容被称为魔数 (magic number)
以下是脚本编写的练习:
写一个脚本,完成以下任务。
1、添加5个用户,user1,,,,user5
2、每个用户的密码同用户名,要求:添加密码完成后不显示passwd执行结果。
3、显示添加成功信息
1 #!/bin/bash 2 # 3 # 4 useradd $1 //添加用户 用户名为传入的第一个参数 5 echo $1 | passwd --stdin $1 &>/dev/null //使用passwd设置密码时,会有第二遍新密码提示输入,作为脚本,不可能等待用户输入,使用--stdin可以从标准输出例如echo,通过管道,提前拿到默认的密码,使其没有第二遍的提示,然后把密码设置成功的返回结果放入数据黑洞中 6 echo "Add User $1 success!" //打印提示信息
这个时候test.sh文件是没有执行权限的
chmod u+x test.sh//给脚本添加执行权限./test.sh user//脚本执行的第一种方式sh test.sh user1//执行的第二种方式
shell中的条件判断
表达式只能返回真或假
条件表达式:
- [ expression ] 这种更常用 表达式两端必须有空格
- test expression
整数大小比较:
- -eq 等于 [ $1 -eq $2 ] 参数1与参数2比较是否相等
- -ne 不等于
- -gt 大于
- -ge 大于等于
- -lt 小于
- -le 小于等于
逻辑关系:在linux 中 命令执行状态 0 为真,其他为假
逻辑与: &&
第一个条件为假时,第二条件不用再判断,最终结果已经有;
第一个条件为真时,第二条件必须得判断;
逻辑或: ||
第一个条件为真时,第二条件不用再判断,最终结果已经有;
第一个条件为假时,第二条件必须得判断;
逻辑非: !
还是对上一个例子加一下逻辑判断
1 #!/bin/bash 2 [ ! $# -eq 1 ] && echo "args are error" && exit 5 3 id $1 &>/dev/null && echo "User $1 exit." && exit 2 4 id $1 &>/dev/null || useradd $1 5 id $1 &>/dev/null && echo "$1" | passwd --stdin $1 &>/dev/null && echo "Add User $1 success!"
第二行 使用了条件判断 $# 特殊变量 获得参数个数 如果不为1 打印提示信息 并 退出;
第三行 id $1 查看用户名为$1的用户信息 结果放入null中,若用户存在返回状态为0,逻辑判断为真,由于是逻辑与判断,仍然会执行后面的命令,打印用户已存在的提示,并退出,此时可以看出通过运用逻辑与的执行特性,替代完成了if else的判断逻辑即:用户存在,给提示,并退出,不存在,继续执行。
第四行代码使用了逻辑或命令,用户不存在 返回状态码非0,逻辑判断为假,对于逻辑或,当第一个判断为假的时候,仍要执行第二个逻辑判断,所以,会执行后面的添加用户操作。
第五行 使用逻辑与命令,当用户存在的时候 设置密码 并打印提示信息,用户添加完成
接着上面的要求,添加完成之后计算系统一共有多个用户。
1 #!/bin/bash 2 [ ! $# -eq 1 ] && echo "args are error" && exit 5 3 id $1 &>/dev/null && echo "User $1 exit." && exit 2 4 id $1 &>/dev/null || useradd $1 5 id $1 &>/dev/null && echo "$1" | passwd --stdin $1 &>/dev/null && echo "Add User $1 success!" 6 COUNT=`wc -l /etc/passwd | awk '{print $1}'` 7 echo "total Users are $COUNT"
第六行 定义一个变量 使用COUNT变量来定义用户总数,所有的命令要用反引号“括起来,使用awk切割字符串,得到用户数量
第七行 打印用户数量
if判断
If 条件 ;then
语句
elif 条件 ; then
语句
else
语句
fi
当then与if同行的时候 之间需要加分号;否则不需要加,最后结束条件判断要加fi 代表结束。
在if判断中的逻辑符号:
-a 与判断
-o 或判断
做如下例子,如果/etc/inittab文件的行数大于50,就显示好大的文件;
1 #!/bin/bash 2 3 C=`wc -l /etc/inittab | cut -d' ' -f1` 4 if [ $C -gt 50 ];then 5 echo "big file." 6 else 7 echo "small file." 8 fi
debug 脚本
bash -n shell文件 :检查文件是否有语法错误。
bash –x shell 文件 :debug 执行文件
算数表达式
- let 算术运算表达式 let C=$A + $B
- $[算术表达式] 括号中没有空格 C = $[$A+$B]
- $((算术表达式)) C=$(($A+$B))
- expr 算术表达式 ,注意:表达式中各操作数及运算符之间要有空格。而且要使用命令引用
C=expr $A + $B
给定一个用户,获取其密码警告期限,然后判断用户密码使用期限是否已经小于警告期限,如果小于,则是显示“WARN” ,否则显示密码还有多少天到期。
1 #!/bin/bash 2 3 if [ ! $# -eq 1 ];then 4 echo "Args errors." 5 exit 3 6 fi 7 8 U_DAY=`grep $1 /etc/shadow | cut -d: -f3` 9 M_DAY=`grep $1 /etc/shadow | cut -d: -f5` 10 W_DAY=`grep $1 /etc/shadow | cut -d: -f6` 11 N_DAY=$[`date +%s`/86400] 12 USE_DAY=$[$N_DAY-$U_DAY] 13 L_DAY=$[$M_DAY-$USE_DAY] 14 15 if [ $L_DAY -le $W_DAY ];then 16 echo "warn" 17 else 18 echo "left day is $L_DAY" 19 fi
for 循环
语法:
for 变量 in 列表 ; do
语句
done
获得列表:
- {1..100}
- seq [起始数] [跨度数] 结束数
- ls /etc 文件列表
实现这个例子:依次向/etc/passwd中的每个用户问好:hello 用户名,并显示用户的shell:
Hello ,root ,your shell :/bin/bash。
1 #!/bin/bash 2 3 C=`wc -l /etc/passwd | cut -d' ' -f1` 4 for I in `seq $C`;do 5 UN=`head -$I /etc/passwd | tail -1 | cut -d: -f1` 6 SH=`head -$I /etc/passwd | tail -1 | cut -d: -f1` 7 echo -e "hello, $UN \t Your shell: $SH" 8 done
计算100以内所有能被3整除的整数的和
1 #!/bin/bash 2 3 SUM=0 4 I=1 5 while true;do 6 if [ $I -gt 100 ];then 7 break 8 fi 9 if [ $[$I%3] -eq 0 ];then 10 SUM=$[$SUM+$I] 11 fi 12 I=$[$I+1] 13 done 14 echo "sum=$SUM"
传给脚本一个参数:目录,输出该目录中文件最大的,文件名和文件大小:
1 #!/bin/bash 2 3 if [ ! -d $1 ];then 4 echo "Args error" 5 exit 3 6 fi 7 8 C=`du -a $1 | wc -l` 9 for I in `seq $C`;do 10 FILE_SIZE=`du -a $1 | sort -rn | head -$I | tail -1 | awk '{print $1}'` 11 FILE_NAME=`du -a $1 | sort -rn | head -$I | tail -1 | awk '{print $2}'` 12 if [ -f $FILE_NAME ];then 13 KB=$[$FILE_SIZE/1024] 14 echo "${KB}KB , $FILE_NAME" 15 break; 16 fi 17 done
- linux下shell编程总结
- linux shell编程总结
- Linux下Shell编程
- linux下shell编程
- Linux下Shell编程
- Linux下shell编程
- Linux 下shell编程
- Linux下Shell编程
- Linux 下shell编程
- Linux下shell编程
- linux下shell编程
- 总结下linux中一些入门级shell编程实例
- linux shell编程实例总结
- linux shell编程实例总结
- linux shell编程实例总结
- Linux shell编程笔记总结
- Linux Shell 编程学习总结
- linux shell编程实例总结
- hdu 1300 Pearls(DP)
- 面试过程总结(经验总结无题目)
- 阻塞非阻塞
- Ubuntu 16.04 jdk 安装和配置
- Reflector 已经out了,试试ILSpy
- linux下shell编程总结
- FATE 完全背包
- 解决“只能通过Chrome网上应用商店安装该程序”的方法
- PAT1004. 成绩排名 (20)
- 集合框架-HashMap集合的案例
- Java村旅游圣地(三)---浅谈设计模式之行为型模式
- struts2中的constant配置详解
- 初学者关于c语言中函数局部变量空间释放的理解
- 对于输出的字符串进行反向输出(不包括汉字)