简单的练习
重要的知识点:
- bash执行脚本是在当前脚本的bash的子进程bash下执行
- source执行脚本是在当前进程中执行
代码范例:
#!/bin/bash#Program:# This program shows "Hello world!" in your screen# These Codes are example's codes in <鸟哥的私房菜1>#history:#2021/11/9 suyisong First release##知识点:# bash执行是在子进程中执行的# source可以在父进程执行__hello(){echo -e "Hello World! \a \n"exit 1 #可作为程序的返回值$?}# 交互式脚本__interactive(){read -rp "Please input your first name: " firstnameread -rp "Please input your last name: " lastnameecho -e "\nYour full name is ${firstname} ${lastname}"}# 建立与日期相关的文件__date(){echo -e "I will use 'touch' command to create 3 files."read -rp 'Please input your filename: ' fileuserfilename=${fileuser:-'datefile'}date1=$(date --date="-1 days" +%Y%m%d)date2=$(date --date="-2 days" +%Y%m%d)date3=$(date +%Y%m%d)file1=${filename}-${date1}file2=${filename}-${date2}file3=${filename}-${date3}touch "${file1}" "${file2}" "${file3}"}# 進行一些數值运算# 可以通过$(()) | declare -i | bc进行运算__numberic(){echo -e 'You should input 2 numbers, I will multipying them!\n'read -rp "first number: " firstnuread -rp "second number: " secondnutotal=$((firstnu*secondnu))echo -e "\nThe result of ${firstnu} x ${secondnu} is ==> ${total}"}__pi(){echo -e "This program will calculate pi value. \n"echo -e "You should input a float number to calculate pi value.\n"read -rp "The scale number(10-10000)?" checkingnum=${checking:-"10"}echo -e "Starting calcuate pi value. Be patient."time echo "scale=${num}; 4*a(1)" | bc -lq}__main(){# __hello__interactive# __date# __numberic# __pi}__main
执行shell的三种方式
- 直接命令执行: ./index.sh或者/dir/to/index.sh,需要文件有rx全选
- bash执行: bash index.sh, 需要有x权限
- source或. : source index.sh或者. index.sh
| 执行方式 | 描述 | 区别 |
| —- | —- | —- |
| 直接命令执行 | |
- 生成进程,可通过ps -e查看
- 子进程bash中执行
| | bash执行 | |
- 由bash执行对应命令,无法通过ps -e查看
- 生成子bash在子进程bash中执行
| | source | |
- 由bash执行对应命令,无法通过ps -e查看
- 在父bash中执行
|
判断式用法
知识点:
- test命令可以进行逻辑判断
- 可以用[]来代替test命令
- shell的传参
- shift进行参数偏移
test命令的测试功能
核心: test命令可以用于测试各种逻辑, 逻辑true则$?为0. 可以用于各种逻辑运算.
test常用的测试参数:
| 参数 | 意义 |
|---|---|
| 文件名和文件类型判断, 如test -e filename表示文件是否存在 | |
| -e | 文件名是否存在 |
| -f | 文件名存在且为file |
| -d | 文件名存在且为目录 |
| -b | 文件名存在且为block device设备 |
| -c | 文件名存在且为一个字符设备文件 |
| -S | 文件名存在且为sockets文件 |
| -p | 文件名存在且为fifo文件 |
| -L | 文件名存在且为链接文件 |
| 文件权限判断 | |
| -r | 文件且在且可读 |
| -w | 可写 |
| -x | 可执行 |
| -u | 文件名存在且具有SUID属性 |
| -g | SGID |
| -k | 文件名存在且具有Sticky bit属性 |
| -s | 文件非空 |
| 文件之间的比较, 如test file1 -nt file2 | |
| -nt | 判断file1比file2新 |
| -ot | 判断file1比file2旧 |
| -ef | 判断f1与f2是否为同一个文件, 根据inode判断 |
| 两个整数之间的判定: test n1 -eq n2 | |
| -eq | 两数值相等 |
| -ne | 两数值不等 |
| -gt | n1 > n2 |
| -lt | n1 < n2 |
| -ge | n1 >= n2 |
| -le | n1 <= n2 |
| 判定字符串的数据 | |
| test -z sting | 判定字符串是否为空, 空则true |
| test -n string | 字符串不为空 |
| test str1 == str2 | |
| test str1 != str2 | |
| 多重条件判定: test -r filename -a -x filename | |
| -o | 或 |
| -a | 与 |
| ! | 非 |
示例:
#!/bin/bash
#Program:
# This program shows "Hello world!" in your screen
# These Codes are example's codes in <鸟哥的私房菜1>
#history:
#2021/11/9 suyisong First release
#
# 知识点:
# test命令为true则$?=0; 负责为1
# test命令一般用法
__test(){
echo -e "Please input a filename, I will check the filename's type and permission:\n\n"
read -rp "Input a filename: " filename
test -z "${filename}" && echo "You must input a filename." && exit 0
test ! -e "${filename}" && echo "The filename ${filename} do not exist" && exit 0
test -f "${filename}" && filetype="regular file"
test -d "${filename}" && filetype="directory"
test -r "${filename}" && perm="readable"
test -w "${filename}" && perm="${perm} writable"
test -x "${filename}" && perm="${perm} executable"
echo "The filename: ${filename} is a ${filetype}"
echo "And the permissions for you are : ${perm}"
}
# 中括号的用法
__bracket(){
read -rp "Please input (Y/N): " yn
[ "${yn}" == "Y" ] || [ "${yn}" == "y" ] && echo "Ok, continue" && exit 0
[ "${yn}" == "N" ] || [ "${yn}" == "n" ] && echo "Oh, interrupt!" && exit 0
echo "I don't konw what your choice is" && exit 0
}
# 命令行给脚本传参方法
# $# $0 $1 $2 $3
# 参数个数 文件名 第一个参数 第二个参数
__param(){
echo "The script name is ==> ${0}"
echo "Total parameter number is ==> ${#}"
[ "$#" -lt 2 ] && echo "The number of parameter is less then 2. Stop here" && exit 0
echo "Your whole parameter is ==> '$*'"
echo "The 1st parameter ==>${1}"
echo "The 2nd parameter ==>${2}"
}
# shift命令可以移除前n个参数
__shift_param(){
echo "Total parameter number is ==> ${#}"
echo "Your whole parameter is ==> '$@'"
shift
echo "Total parameter number is ==> ${#}"
echo "Your whole parameter is ==> '$@'"
shift 3
echo "Total parameter number is ==> ${#}"
echo "Your whole parameter is ==> '$@'"
}
# __test
# __bracket
# __param "$@"
__shift_param "$@"
条件判断式用法
知识点:
- if和case的用法
练习:
#!/bin/bash
#Program:
# This program shows "Hello world!" in your screen
# These Codes are example's codes in <鸟哥的私房菜1>
#history:
#2021/11/10 suyisong First release
#
__if(){
read -rp "Please input (Y/N): " yn
if [ "${yn}" == "Y" ] || [ "${yn}" == "y" ]; then
echo "Ok, continue"
exit 0
fi
if [ "${yn}" == "N" ] || [ "${yn}" == "n" ]; then
echo "Oh, interrupt!"
exit 0
fi
echo "I don't konw what your choice is" && exit 0
}
__if_else(){
read -rp "Please input (Y/N): " yn
if [ "${yn}" == "Y" ] || [ "${yn}" == "y" ]; then
echo "Ok, continue"
exit 0
elif [ "${yn}" == "N" ] || [ "${yn}" == "n" ]; then
echo "Oh, interrupt!"
exit 0
else
echo "I don't konw what your choice is" && exit 0
fi
}
__hello(){
if [ "${1}" == "hello" ]; then
echo "Hello, how are you!"
elif [ -z "${1}" ]; then
echo "You must input parameters, ex>{${0} someword}"
else
echo "The only parameter is 'hello', ex>{${0} hello}"
fi
}
# 一个demo
# 描述: 当兵退伍时输入退伍日期, 计算还有多少天退伍
__demo(){
echo "This parogram will try to calculate : "
echo "How many days before your demobilization date..."
read -rp "Please input your demobilization date (YYYMMDD ex>20150716):" date2
date_d=$(echo "${date2}" | grep '[0-9]\{8\}')
if [ -z "${date_d}" ]; then
echo "You input the wrong date format..."
exit 1
fi
declare -i date_dem=$(date --date="${date2}" +%s)
declare -i date_now=$(date +%s)
declare -i date_total_s=$((date_dem - date_now))
declare -i date_d=$((date_total_s/60/60/24))
if [ "${date_total_s}" -lt "0" ]; then
echo "You had been demobilization before: " $(( -1 * date_d )) " ago"
else
declare -i date_h=$(( $((date_total_s-date_d*60*60*24))/60/60 ))
echo "You will demobilize after ${date_d} days and ${date_h} hours"
fi
}
__case(){
case "${1}" in
"hello")
echo "Hello, how are you!"
;;
"")
echo "You must input parameters, ex>{${0} someword}"
;;
*)
echo "The only parameter is 'hello', ex>{${0} hello}"
;;
esac
}
__printit(){
echo -n "Your choice is "; echo "${1}" | tr 'a-z' 'A-Z'
}
__func(){
echo "This program will print your selection !"
case "${1}" in
"one"|"two"|"three")
__printit "${1}"
;;
*)
echo "Usage ${0} {one|two|three}"
;;
esac
}
# __if
# __if_else
# __hello $@
# __demo
# __case $@
__func $@
循环
知识点:
- while do done和until do done可以根据条件循环
- for do done 时固定循环
- 产生随机数的方法seq 1 100和{1..100}
- for do done的第二种语法
- 数组和随机数的搭配
练习:
#!/bin/bash
#Program:
# This program shows "Hello world!" in your screen
# These Codes are example's codes in <鸟哥的私房菜1>
#history:
#2021/11/9 suyisong First release
#
__while(){
while [ "${yn}" != "yes" -a "${yn}" != "YES" ]; do
read -rp "please input yes/YES to stop:" yn
done
echo "OK! you input the correct answer."
}
__until(){
until [ "${yn}" == "yes" -o "${yn}" == "YES" ]; do
read -rp "please input yes/YES to stop:" yn
done
echo "OK! you input the correct answer."
}
__cal_1_100(){
s=0
i=0
while [ "${i}" != "100" ]; do
i=$((i+1))
s=$((s+i))
done
echo "The Result of '1+2+3+...+100' is ==> ${s}"
unset s
unset i
}
__for(){
for animal in dog cat elephant; do
echo "There are ${animal}s..."
done
}
__for_passwd(){
users=$(cut -d ':' -f1 /etc/passwd)
for user in $users;do
id "${user}"
done
}
# seq可以产生连续的字符, {1..100}也能产生连续的字符
__for_ping(){
network="192.168.1"
for sitenu in $(seq 1 100); do
ping -c 1 -w 1 ${network}."${sitenu}" &>/dev/null && result=0 || result=1
if [ "${result}" == 0 ]; then
echo "Server ${network}.${sitenu} is UP."
else
echo "Server ${network}.${sitenu} is DOWN."
fi
done
}
__for_2(){
read -rp "Please input a number, I will count for 1+2+...+your_input: " nu
s=0
for (( i=1; i<=nu; i=i+1 )); do
s=$((s+i))
done
echo "The result of '1+2+3+...+${nu}' is ==>${s}"
}
# 示例
# 随机获取中午吃什么
__demo(){
eat[1]="肯当当汉堡"
eat[2]="肯爷爷汉堡"
eat[3]="彩虹日式便当"
eat[4]="曱甴"
eat[5]="乡干部处"
eat[6]="hah"
eat[7]="ddd"
eat[8]="附近哈"
eat[9]="就会发"
eatnum=9
eated=0
while [ "${eated}" -lt 3 ]; do
check=$(( RANDOM * eatnum /32767 + 1 ))
mycheck=0
if [ "${eated}" -ge 1 ]; then
for i in $(seq 1 ${eated}); do
if [ "${eatedcon[$i]}" == $check ]; then
mycheck=1
fi
done
fi
if [ ${mycheck} == 0 ]; then
echo "your may eat ${eat[$check]}"
eated=$(( eated + 1 ))
eatedcon[${eated}]=${check}
fi
done
}
# __while
# __until
# __cal_1_100
# __for
# __for_passwd
# __for_ping
# __for_2
__demo
shell脚本的跟踪与调试
核心: 使用bash命令直接进行调试.
bash [-nvx] file
选项与参数:
-n : 不执行脚本仅查询语法
-v : 执行脚本前先输出脚本
-x : 将使用到的脚本内容输出
重点:
- sh -x .sh进行程序的debug
