shell script

写shell脚本

1.交互式脚本

read -p "Please input your first name:" firstname
read -p "Please input your last name:" lastname
echo -e "\nYour full name is:" $firstname $lastname

2.随日期变化

read -p "Please input your first name:" firstuser
filename=${fileuser:-"filename"} #当$fileuser没有设定或为控制,则用"filename"作为回传值
date1=$(date --date='2 days ago' +%Y%m%d) #前两天的日期
date2=$(date --date='1 days ago' +%Y%m%d) #前一天的日期
date3=$(date +%Y%m%d) #今天的日期
file1=${filename}${date1}
file2=${filename}${date2}
file3=${filename}${date3}

touch "file1"
touch "file2"
touch "file3"

3.数值运算

变量名=$((运算内容))

echo $((3*3))

4.利用test进行测试

test -e /dir && echo "exist" || echo "no exist" #判断/dir是否存在

shell中的${},##, %% , :- ,:+, ? 的使用

假设我们定义了一个变量为:
file=/dir1/dir2/dir3/my.file.txt

可以用${ }分别替换得到不同的值:
${file#*/}:删掉第一个/ 及其左边的字符串:dir1/dir2/dir3/my.file.txt
${file##*/}:删掉最后一个/  及其左边的字符串:my.file.txt
${file#*.}:删掉第一个.  及其左边的字符串:file.txt
${file##*.}:删掉最后一个.  及其左边的字符串:txt
${file%/*}:删掉最后一个 /  及其右边的字符串:/dir1/dir2/dir3
${file%%/*}:删掉第一个/  及其右边的字符串:(空值)
${file%.*}:删掉最后一个 .  及其右边的字符串:/dir1/dir2/dir3/my.file
${file%%.*}:删掉第一个 .   及其右边的字符串:/dir1/dir2/dir3/my

记忆的方法为:
'#' 是 去掉左边(键盘上#在 $ 的左边)
%是去掉右边(键盘上% 在$ 的右边)
单一符号是最小匹配;两个符号是最大匹配
${file:0:5}:提取最左边的5 个字节:/dir1
${file:5:5}:提取第5 个字节右边的连续5个字节:/dir2

也可以对变量值里的字符串作替换:
${file/dir/path}:将第一个dir 替换为path:/path1/dir2/dir3/my.file.txt
${file//dir/path}:将全部dir 替换为path:/path1/path2/path3/my.file.txt

利用${ } 还可针对不同的变数状态赋值(沒设定、空值、非空值): 
${file-my.file.txt} :假如$file 沒有设定,則使用my.file.txt 作传回值。(空值及非空值時不作处理) 
${file:-my.file.txt} :假如$file 沒有設定或為空值,則使用my.file.txt 作傳回值。(非空值時不作处理)
${file+my.file.txt} :假如$file 設為空值或非空值,均使用my.file.txt 作傳回值。(沒設定時不作处理)
${file:+my.file.txt} :若$file 為非空值,則使用my.file.txt 作傳回值。(沒設定及空值時不作处理)
${file=my.file.txt} :若$file 沒設定,則使用my.file.txt 作傳回值,同時將$file 賦值為my.file.txt 。(空值及非空值時不作处理)
${file:=my.file.txt} :若$file 沒設定或為空值,則使用my.file.txt 作傳回值,同時將$file 賦值為my.file.txt 。(非空值時不作处理)
${file?my.file.txt} :若$file 沒設定,則將my.file.txt 輸出至STDERR。(空值及非空值時不作处理)


${file:?my.file.txt} :若$file 没设定或为空值,则将my.file.txt 输出至STDERR。(非空值時不作处理)

${#var} 可计算出变量值的长度:


${#file} 可得到27 ,因为/dir1/dir2/dir3/my.file.txt 是27个字节

5.条件判断式

if [ 条件判断式 ]; then
    ...
fi

如:

if [ "$Yn" == "Y" ] || [ "$yn" == "y" ]; then
    echo "OK"
    exit 0
fi

*中括号两边加空格,变量也要加双引号

if [ situation1 ]; then
    ...
elif [ situation2 ]; then
    ...
else
    ...
fi

####实例练习

计算毕业时间

!/bin/bash
# program:
#     You input your graduation date, I calculate how many days before you graduate.
# History:
# 2018/7/12 yyqiao 1.0 version

#1. 输入说明
echo "This program will try to calculate:"
echo "How many days before your graduation date..."
read -p "Please input your graduation data (YYYYMMDD ex>20180712):" date2

#2. 判断输入内容格式是否正确

date_d=$(echo $date2 | grep '[0-9]\{8\}') #是否有8位数字
if [ "$date_d" == "" ]; then
    echo "Wrong input"
    exit 1
fi

#3.计算日期

declare -i date_gra=`date --date="$date_d" +%s`
declare -i date_now=`date +%s`
declare -i date_total=$(($date_gra-$date_now)) 
declare -i date_d=$(($date_total/60/60/24))

if [ "$date_total" -gt "0" ]; then
    declare -i date_h=$(($date_total-$date_d*60*60*24)/60/60)
    echo "You will graduate after $date_d days and $date_h hours"
else
    echo "You had been graduation before: " $((-1*$date_d)) " ago"
fi

6.function 功能

function funName () {
    ...
}

7.循环loop

while [ condition ]
do
    ...
done

until [ condition ]
do
    ...
done

for var in con1 con2 con3 ...
do
    ...
done

如:
for vari in $(seq 1 100)
do 
    ...
done

filelist =$(ls $dir)
for file in filelist
do
    ...
done

for ((初始值;限制值;执行步长))
do
    ...
done

如:
for(( i=1; i<=9; i=i+1 ))
do
    ...
done

8.shell script 调试

sh [-nvx] script.sh
-n: 不要执行,仅检查语法
-v: 执行前先将script内容输出到屏幕上
-x: 将script显示在频幕上
Thanks for your support!