1、简介2、read3、运算工具4、if/then结构5、while循环6、for循环 一、简介1、什么是shellshell是用户与系统交互作用的界面。shell是一种命令解释程序,同时也是一种高级程序设计语言2、shell常见种类Bourne Shell(/usr/bin/sh或/bin/sh)Bourne Again Shell(/bin/bash)C Shell(/usr/bin/csh)K Shell(/usr/bin/ksh)Shell for Root(/sbin/sh)其中:Bash在日常工作中被广泛使用;同时,Bash也是大多数Linux系统默认的Shell;3、shell局限性1.1、需要耗费大量资源的任务,特别是对执行速度要求较高的场合1.2、涉及大量的数学计算1.3.、关键性应用(数据库,网站等)1.4.、设计图形或者GUI的应用1.5.、需要直接访问硬件1.6.、开发闭源的应用(相对于开源)4、基础文件系统:Linux 的文件系统是一个包含了目录和文件的分层的组织结构,位于最顶端的叫做根目录(root directory),用斜杠/ 来表示目录: 是一种包含目录项的文件,每个目录项中都包含了文件名文件名: 目录的内容称为目录项,目录项包含了文件名,只有两种字符不允许出现在文件名中:斜杠,空字符(ASCII 值为0),斜杠用于分隔路径中的文件名,空字符用来表示路径的结尾。文件名的长度通常可以达到255个字符路径: 一系列文件名连起来,用斜杠分隔,就叫做路径,路径用于表示文件的位置;以斜杠开头的路径叫做绝对路径,否则为相对路径,相对路径相对于当前工作目录返回码:所有命令都有一个返回值,用0-255之间的整数来表示;脚本就是一个命令,它也有返回值,另外,脚本里面的函数也有返回值退出脚本的正规方法是明确地用命令exit
来退出,如:exit 0;exit $? 二、read1、定义read是一个buildin命令,主要完成对参数的赋值,类似C语言中的scanf;其不仅可以赋值变量,还可以赋值数组;其输入不仅是屏幕,还可以是文件描述符2、实操# read a --输入字符串,将字符串赋值给变量 a;# echo $ahello world!!# read name sex age --同时分别给三个变量赋值,输入分隔符默认为 空格符zhangsan male 50# unset name sex age --删除变量# IFS=';' --将 read 的输入分隔符改为 ';'# vim test.sh#!/bin/bashprompt="Please enter your name:"read -p "$prompt" nameecho "Greetings $name" 三、运算工具1、简单数学运算# echo $((1+2**2-3*4/5%6)) --输出计算结果到屏幕# a=$((1+2**2-3*4/5%6)) --把计算结果赋给变量a# ((a=1+2**2-3*4/5%6)) --同上# echo "scale=3;10/3" | bc --bc计算器;保留小数点后三位# echo "2^10" | bc --bc计算器;计算2的10次方# awk 'BEGIN{print 1/3}' --awk计算2、获取随机数# od -N4 -tu4 /dev/urandom | sed -n '1s/.* //p' --获取一个7位数的号码# od -Ad -w24 -tu4 /dev/urandom --获取随机数# od -tu8 /dev/urandom --获取随机数# od -tu8 /dev/urandom | sed -r 's/^[0-9]+\s+//' | sed -r 's/\s+/\n/g' |cut -b1-8 |sed -r -n '/^.{8}$/p' | sed 's/^/186/' |head -n5000 |vi - --获取一万个电话号码# od -N40000 -tu4 /dev/urandom | sed -r 's/^[0-9]+(\s+)?//' | sed -r 's/\s+/\n/g' | grep -vE '^\s*$' > 10k_random --生成一万个随机数# sed -r -n '/^.{8}$/p' 10k_random | head -n 100000 | sed 's/^/186/' > phone_num3、获取数字序列# seq 10 --获取1到10# seq 1 2 10 --获取1到10,步长为2# seq 10 100 --获取10到100# seq 10 -1 1 --倒序,10到1 四、if/then实例1、判断字符 "a" 是否等于 "A"# vim test.sh#!/bin/bashif [[ "a" = "A" ]]; thenif [ "a" = "A" ]; then echo "a equals A"else echo "a no equals A"fi2、判断/root/test/test.sh是否存在并具有可执行权限# vim test.sh#!/bin/bashif test -x /root/test/test.sh;then echo "/root/test/test.sh is executable"fi3、判断系统是否存在 root 用户# vim test.sh#!/bin/bashif grep -E --color=auto ^root: /etc/passwd; then echo "user root exists"fi4、判断文件类型# vim test.sh#!/bin/bashfunction isSymbolicLink() { file=$1 flag=$(ls -ld $file | cut -b1) test "$flag" = "1" return $?}file=$1if isSymbolicLink $file; then echo "Symbolic Link"elif test -d $file; then echo "Directory file"elif test -f $file; then echo "Regular file"elif test -b $file; then echo "Block special"elif test -c $file; then echo "Character special"elif test -p $file; then echo "Named pipe"elif test -S $file; then echo "Socket"else echo "Unkown"fi5、判断输入数字的大小# vim test.sh#!/bin/bashnum=$1if test "$num" -lt 10 ;then echo "小数字"elif test "$num" -lt 20;then echo "中数字"elif test "$num" -lt 30;then echo "大数字"else echo "超大数字"fi6、从标准输入获取一个数字,并根据其大小输出指定字符串# vim test.sh#!/bin/bashecho -n "Enter a number: "read numif [ "$num" -lt 100 ]; thenecho "小于100"elif [ "$num" -ge 100 -a "$num" -lt 200 ]; thenecho "大于等于100小于200"elif [ "$num" -ge 200 -a "$num" -lt 300 ]; thenecho "大于等于200小于300"elseecho "其它数字"fi 五、wihle循环1、认识测试 while 关键字后面一条命令的返回码,条件为真时,程序读入while循环体中的指令;0为真。循环体如下:while [] --while 后面运行 [ ] 命令,测试 [ ] 命令的返回码cat /filename | while read line --while 后面运行read 命令,测试 read 命令的返回码do......done2、循环控制语句continue --终止当前循环,开始下一个循环break --终止当前循环,并退出循环体exit --终止当前脚本3、实例# vim test.sh --区分 continue 与 break 的区别#!/bin/bashwhile truedosleep 1echo testcontinue/breakechodone# vim test.sh --区分 break 与 exit 的区别#!/bin/bashwhile test -e /data/test/test.shdoecho "exists"sleep 1break/exitdoneecho "loop end"# vim test.sh --寻找我们给定的路径,直到寻到为止 #!/bin/bashif test $# -ne 1;thenecho "wrong paraneter" >&2exitfipath=$1while test ! -e "$path"dosleep 1echo "don't found!!!"doneecho "found"# vim test.sh --脚本运行指定的时间,时间一到就退出;单位为 s#!/bin/bashif test $# -ne 1;thenecho "Usage: $(basename $0) TIME" >&2exit 1fitimeLength=$1beginTime=$(date +%s)endTime=$(( $beginTime + $timeLength ))---------------------------------------------------------while test $(date +%s) -lt "$endTime"doecho "processing....."sleep 1done---------------------------------------------------------while truedoif test $(date +%s) -ge "$endTime";thenbreakfiecho "processing....."sleep 1done---------------------------------------------------------echo "time out"# vim test.sh --循环读取文件的每一行,并计算每行的字符个数#!/bin/bashfile=$1---------------------------------------------------------totalLines=$(wc -l < $file)line=1while test $line -le $totalLinesdolineData=$(sed -n "${line}p" $file)len=$(echo -n $lineData | wc -c)echo "line ${line}: $len"line=$(( $line + 1 ))done---------------------------------------------------------line=1while read lineDatadolen=$(echo $lineData | wc -c)echo "line ${line}: $len"line=$(( $line + 1 ))done < $file---------------------------------------------------------# vim test.sh -- 打印出10行hello world;<(seq 10)相当于一个文件路径;称之为进程置换#!/bin/bashwhile read numdoecho "hello world"done < <(seq 10)---------------------------------------------------------n=1while [ $n -le 10 ]doecho "hello world"n=$((n+1))done---------------------------------------------------------# vim test.sh --创建一个不尽的循环,要求循环运行1分钟后自动终止#!/bin/bashstart_time=$(date +%s)while truedocur_time=$(date +%s)test $((cur_time - start_time)) -ge 10 && breaktime=$((cur_time - start_time))echo "time is $time......"sleep 1done# vim test.sh --先用while 循环创建100个.txt文件;再将所有文件后缀名改为 .html#!/bin/bashcount=100---------------------------------------------------------seq $count | while read idotouch ${i}.txtdonels -1 *.txt | while read oldnamedonewname=$(echo $oldname | sed 's/.txt$/.html/')mv $oldname $newnamedone---------------------------------------------------------while read idotouch ${i}.txtdone < <( seq $count )while read oldnamedonewname=$(echo $oldname | sed 's/.txt$/.html/')mv $oldname $newnamedone < <(ls -1 *.txt )# vim test.sh --计算出1000 之内的偶数的和;不能使用管道,因为管道会生成子进程#!/bin/bashsum=0while read numdosum=$(( $sum + $num ))done < <(seq 2 2 998)echo "sum: $sum "# vim test.sh --批量添加100个邮件用户,用户名为u1 至u100,密码为abc,登录shell 为/sbin/nologin,只属于email组#!/bin/bashpassword=abcgroup=emailgrep -Eq "^${group}:" /etc/group || groupadd $groupwhile read idouseradd u${i} -N -g $group -s /sbin/nologinpasswd u${i} --stdin <<< "$password"done < <(seq 100)# vim test.sh --批量删除刚刚创建的100个邮件用户#!/bin/bashwhile read idouserdel -r u${i}done < <(seq 100 六、for 循环在一系列由分隔符隔开的字符串中,按顺序每次取其中之一,当取完之后,循环结束每次取出的字符串会被保存在一个变量中,可以在循环体内使用该变量由分隔符隔开的字符串可以通过以下方法提供:1、手动输入字符串,用于循环指定次数# vim test.sh#!/bin/bashfor i in 1 2 3doecho $idon2、由变量提供字符串# vim test.sh#!/bin/bashFILES="/bin/bash /bin/ls /bin/cat"for file in $FILES doecho $filedone3、程序生成的字符串# vim test.sh#!/bin/bashfor n in $(seq 11)do echo $ndone4、由shell 展开而生成,循环目录中的文件# vim test.sh#!/bin/bashfor f in /etc/init.d/*doecho $fdone# vim test.sh5、打印出/dev 下面所有以 loop 开头的文件的文件名# vim test.sh#!/bin/bashfor file in /dev/loop*doecho $(basename $file)done6、计算出1000 之内的偶数的和# vim test.sh#!/bin/bashsum=0for number in $(seq 2 2 998)do sum=$(( $sum + $number ))doneecho "total: $sum"7、批量添加100个邮件用户,用户名为u1 至u10,密码为abc,登录shell 为/sbin/nologin,只属于email组# vim test.sh#!/bin/bashfunction checkGid() {gid=$1if ! grep -qE "^$gid:" /etc/group; thengroupadd $gidfi}function isRoot() {id=$(id | awk -F "[=(]" '{print $2}')if test "$id" -ne 0; thenecho "must be root" >&2exit 1fi}count=10namePrefix=upassword=abcshell=/sbin/nologingid=emailisRootcheckGid $gidfor num in $(seq $count)doname=${namePrefix}${num}useradd $name -s $shell -g $gid &> /dev/nullif test $? -ne 0; thenecho "failed to create $name" >&2elseecho "created successfully -- $name"echo "$password" | passwd --stdin $name &> /dev/nullif test $? -ne 0; thenecho "failed to change password for $name" >&2elseecho "password changed successfully -- $name"fifidone8、获取局域网内所有电脑的IP 和MAC 地址的对应表# vim test.sh#!/bin/bashipPrefix=192.168.1.startIp=1endIp=254for num in $(seq $startIp $endIp)doip=${ipPrefix}$numping -W1 -c1 $ip &>/dev/null &donewaitarp -n | sed '/incomplete/d' | awk '{print $1,$3}'| cat | sort -n -t '.' -k4,4 | column -t9、打印出九九乘法表# vim test.sh#!/bin/bashfor row in $(seq 9)dofor col in $(seq $row)doecho -n "${col}x${row}=$(( $col * $row )) "doneechodone | column -t10、简陋计算器#!/bin/bashvarnum=3if test "$#" -ne "$varnum"; thenecho "wrong argument" >&2exit 1finum1=$1num2=$3operator=$2if test "$operator" = "x";thenoperator="*"fiif test "$operator" = "/" -a "$num2" = 0; thenecho "division by 0" >& 2exit 1firesult=$(( $num1 $operator $num2 ))echo "$result"注意:乘法的处理;被除数为0时的处理11、把指定目录下的某些文件复制到指定的目录,要求:#1. 从命令行参数接收两个参数,分别是源目录和目标目录#2. 如果源目录不存在,应该报错#3. 如果目标目录不存在,就创建一个#4. 如果目标已经存在但不是目录,就报错#5. 只复制常规文件,软链接文件#6. 对于常规文件,只复制大小小于1M 的文件# vim /test.sh#!/bin/bashfunction displayHelp(){echo "Usage: $(basename $0) SRCDIR DSTDIR"}function getSize(){file=$1size=$(ls -l $file | awk '{print $5}')echo $size}if test $# -ne 2; thendisplayHelp >&2exit 1fisrcdir=$1dstdir=$2if test ! -d "$srcdir"; thenecho "$srcdir not exists or is not a directory" >&2exit 1fiif test ! -e "$dstdir"; thenmkdir "$dstdir"fiif test ! -d "$dstdir"; thenecho "$dstdir is not a directory" >&2exit 1fifor file in $srcdir/*doif test -L $file; thencp -a $file $dstdir/elif test -f $file; then---------------------------------------------------size=$(getSize $file)if test "$size" -lt 1048576; thencp -a $file $dstdir/fi---------------------------------------------------find $file -type f -size -1024k -exec cp -a {} $dstdir/ \;---------------------------------------------------fidone
以上就是什么是shell?shell常见种类的介绍的详细内容,更多请关注风君子博客其它相关文章!