shell_script1金沙官网线上:

1、简介

2、read

3、运算工具

4、if/then结构

5、while循环

6、for循环

 

一、简介

1、什么是shell

shell是用户与系统交互作用的界面。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 [code]来退出,如:exit 0;exit $?

 

二、read

1、定义

read是一个buildin命令,主要完成对参数的赋值,类似C语言中的scanf;

其不仅可以赋值变量,还可以赋值数组;

其输入不仅是屏幕,还可以是文件描述符

2、实操

# read a --输入字符串,将字符串赋值给变量 a;# echo $a

hello world!!

# read name sex age --同时分别给三个变量赋值,输入分隔符默认为 空格符

zhangsan male 50

# unset name sex age --删除变量

# IFS=';' --将 read 的输入分隔符改为 ';'

# vim test.sh

#!/bin/bash

prompt="Please enter your name:"

read -p "$prompt" name

echo "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_num

3、获取数字序列

# 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/bash

if [[ "a" = "A" ]]; then

if [ "a" = "A" ]; then

  echo "a equals A"

else

  echo "a no equals A"

fi

2、判断/root/test/test.sh是否存在并具有可执行权限

# vim test.sh

#!/bin/bash

if test -x /root/test/test.sh;then

  echo "/root/test/test.sh is executable"

fi

3、判断系统是否存在 root 用户

# vim test.sh

#!/bin/bash

if grep -E --color=auto ^root: /etc/passwd; then

  echo "user root exists"

fi

4、判断文件类型

# vim test.sh

#!/bin/bash

function isSymbolicLink() {

  file=$1

  flag=$(ls -ld $file | cut -b1)

  test "$flag" = "1"

  return $?

}

file=$1

if 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"

fi

5、判断输入数字的大小

# vim test.sh

#!/bin/bash

num=$1

if test "$num" -lt 10 ;then

  echo "小数字"

elif test "$num" -lt 20;then

  echo "中数字"

elif test "$num" -lt 30;then

  echo "大数字"

else

  echo "超大数字"

fi

6、从标准输入获取一个数字,并根据其大小输出指定字符串

# vim test.sh

#!/bin/bash

echo -n "Enter a number: "

read num

if [ "$num" -lt 100 ]; then

echo "小于100"

elif [ "$num" -ge 100 -a "$num" -lt 200 ]; then

echo "大于等于100小于200"

elif [ "$num" -ge 200 -a "$num" -lt 300 ]; then

echo "大于等于200小于300"

else

echo "其它数字"

fi

 

五、wihle循环

1、认识

测试 while 关键字后面一条命令的返回码,条件为真时,程序读入while循环体中的指令;0为真。循环体如下:

while [] --while 后面运行 [ ] 命令,测试 [ ] 命令的返回码

cat /filename | while read line       --while 后面运行read 命令,测试 read 命令的返回码

do

......

done

2、循环控制语句

continue --终止当前循环,开始下一个循环

break --终止当前循环,并退出循环体

exit --终止当前脚本

3、实例

# vim test.sh --区分 continue 与 break 的区别

#!/bin/bash

while true

do

sleep 1

echo test

continue/break

echo

done

# vim test.sh --区分 break 与 exit 的区别

#!/bin/bash

while test -e /data/test/test.sh

do

echo "exists"

sleep 1

break/exit

done

echo "loop end"

# vim test.sh --寻找我们给定的路径,直到寻到为止

#!/bin/bash

if test $# -ne 1;then

echo "wrong paraneter" >&2

exit

fi

path=$1

while test ! -e "$path"

do

sleep 1

echo "don't found!!!"

done

echo "found"

# vim test.sh --脚本运行指定的时间,时间一到就退出;单位为 s

#!/bin/bash

if test $# -ne 1;then

echo "Usage: $(basename $0) TIME" >&2

exit 1

fi

timeLength=$1

beginTime=$(date +%s)

endTime=$(( $beginTime + $timeLength ))


while test $(date +%s) -lt "$endTime"

do

echo "processing....."

sleep 1

done


while true

do

if test $(date +%s) -ge "$endTime";then

break

fi

echo "processing......"

sleep 1

done


echo "time out"

# vim test.sh --循环读取文件的每一行,并计算每行的字符个数

#!/bin/bash

file=$1


totalLines=$(wc -l < $file)

line=1

while test $line -le $totalLines

do

lineData=$(sed -n "${line}p" $file)

len=$(echo -n $lineData | wc -c)

echo "line ${line}: $len"

line=$(( $line + 1 ))

done


line=1

while read lineData

do

len=$(echo $lineData | wc -c)

echo "line ${line}: $len"

line=$(( $line + 1 ))

done < $file


# vim test.sh -- 打印出10行hello world;<(seq 10)相当于一个文件路径;称之为进程置换

#!/bin/bash

while read num

do

echo "hello world"

done < <(seq 10)


n=1

while [ $n -le 10 ]

do

echo "hello world"

n=$((n+1))

done


# vim test.sh --创建一个不尽的循环,要求循环运行1分钟后自动终止

#!/bin/bash

start_time=$(date +%s)

while true

do

cur_time=$(date +%s)

test $((cur_time - start_time)) -ge 10 && break

time=$((cur_time - start_time))

echo "time is $time......"

sleep 1

done

# vim test.sh --先用while 循环创建100个.txt文件;再将所有文件后缀名改为 .html

#!/bin/bash

count=100


seq $count | while read i

do

touch ${i}.txt

done

ls -1 *.txt | while read oldname

do

newname=$(echo $oldname | sed 's/.txt$/.html/')

mv $oldname $newname

done


while read i

do

touch ${i}.txt

done < <( seq $count )

while read oldname

do

newname=$(echo $oldname | sed 's/.txt$/.html/')

mv $oldname $newname

done < <(ls -1 *.txt )

# vim test.sh --计算出1000 之内的偶数的和;不能使用管道,因为管道会生成子进程

#!/bin/bash

sum=0

while read num

do

sum=$(( $sum + $num ))

done < <(seq 2 2 998)

echo "sum: $sum "

# vim test.sh --批量添加100个邮件用户,用户名为u1 至u100,密码为abc,登录shell 为/sbin/nologin,只属于email组

#!/bin/bash

password=abc

group=email

grep -Eq "^${group}:" /etc/group || groupadd $group

while read i

do

useradd u${i} -N -g $group -s /sbin/nologin

passwd u${i} --stdin <<< "$password"

done < <(seq 100)

# vim test.sh --批量删除刚刚创建的100个邮件用户

#!/bin/bash

while read i

do

userdel -r u${i}

done < <(seq 100

 

六、for 循环

在一系列由分隔符隔开的字符串中,按顺序每次取其中之一,当取完之后,循环结束

每次取出的字符串会被保存在一个变量中,可以在循环体内使用该变量

由分隔符隔开的字符串可以通过以下方法提供:

1、手动输入字符串,用于循环指定次数

# vim test.sh

#!/bin/bash

for i in 1 2 3

do

echo $i

don

2、由变量提供字符串

# vim test.sh

#!/bin/bash

FILES="/bin/bash /bin/ls /bin/cat"

for file in $FILES

do

echo $file

done

3、程序生成的字符串

# vim test.sh

#!/bin/bash

for n in $(seq 11)

do

  echo $n

done

4、由shell 展开而生成,循环目录中的文件

# vim test.sh

#!/bin/bash

for f in /etc/init.d/*

do

echo $f

done

# vim test.sh

5、打印出/dev 下面所有以 loop 开头的文件的文件名

# vim test.sh

#!/bin/bash

for file in /dev/loop*

do

echo $(basename $file)

done

6、计算出1000 之内的偶数的和

# vim test.sh

#!/bin/bash

sum=0

for number in $(seq 2 2 998)

do

  sum=$(( $sum + $number ))

done

echo "total: $sum"

7、批量添加100个邮件用户,用户名为u1 至u10,密码为abc,登录shell 为/sbin/nologin,只属于email组

# vim test.sh

#!/bin/bash

function checkGid() {

gid=$1

if ! grep -qE "^$gid:" /etc/group; then

groupadd $gid

fi

}

function isRoot() {

id=$(id | awk -F "[=(]" '{print $2}')

if test "$id" -ne 0; then

echo "must be root" >&2

exit 1

fi

}

count=10

namePrefix=u

password=abc

shell=/sbin/nologin

gid=email

isRoot

checkGid $gid

for num in $(seq $count)

do

name=${namePrefix}${num}

useradd $name -s $shell -g $gid &> /dev/null

if test $? -ne 0; then

echo "failed to create $name" >&2

else

echo "created successfully -- $name"

echo "$password" | passwd --stdin $name &> /dev/null

if test $? -ne 0; then

echo "failed to change password for $name" >&2

else

echo "password changed successfully -- $name"

fi

fi

done

8、获取局域网内所有电脑的IP 和MAC 地址的对应表

# vim test.sh

#!/bin/bash

ipPrefix=192.168.1.

startIp=1

endIp=254

for num in $(seq $startIp $endIp)

do

ip=${ipPrefix}$num

ping -W1 -c1 $ip &>/dev/null &

done

wait

arp -n | sed '/incomplete/d' | awk '{print $1,$3}'| cat | sort -n -t '.' -k4,4 | column -t

9、打印出九九乘法表

# vim test.sh

#!/bin/bash

for row in $(seq 9)

do

for col in $(seq $row)

do

echo -n "${col}x${row}=$(( $col * $row )) "

done

echo

done | column -t

10、简陋计算器

#!/bin/bash

varnum=3

if test "$#" -ne "$varnum"; then

echo "wrong argument" >&2

exit 1

fi

num1=$1

num2=$3

operator=$2

if test "$operator" = "x";then

operator="*"

fi

if test "$operator" = "/" -a "$num2" = 0; then

echo "division by 0" >& 2

exit 1

fi

result=$(( $num1 $operator $num2 ))

echo "$result"

注意:乘法的处理;被除数为0时的处理

11、把指定目录下的某些文件复制到指定的目录,要求:

#1. 从命令行参数接收两个参数,分别是源目录和目标目录

#2. 如果源目录不存在,应该报错

#3. 如果目标目录不存在,就创建一个

#4. 如果目标已经存在但不是目录,就报错

#5. 只复制常规文件,软链接文件

#6. 对于常规文件,只复制大小小于1M 的文件

# vim /test.sh

#!/bin/bash

function displayHelp()

{

echo "Usage: $(basename $0) SRCDIR DSTDIR"

}

function getSize()

{

file=$1

size=$(ls -l $file | awk '{print $5}')

echo $size

}

if test $# -ne 2; then

displayHelp >&2

exit 1

fi

srcdir=$1

dstdir=$2

if test ! -d "$srcdir"; then

echo "$srcdir not exists or is not a directory" >&2

exit 1

fi

if test ! -e "$dstdir"; then

mkdir "$dstdir"

fi

if test ! -d "$dstdir"; then

echo "$dstdir is not a directory" >&2

exit 1

fi

for file in $srcdir/*

do

if test -L $file; then

cp -a $file $dstdir/

elif test -f $file; then


size=$(getSize $file)

if test "$size" -lt 1048576; then

cp -a $file $dstdir/

fi


find $file -type f -size -1024k -exec cp -a {} $dstdir/ ;


fi

done

本文由金沙官网线上发布于操作系统,转载请注明出处:shell_script1金沙官网线上:

您可能还会对下面的文章感兴趣: