Shell 脚本

脚本以 #!/bin/bash 开头。

输出 Hello World !/usr/test.txt(如果输入文本中带引号和 $,需要用 \ 进行转义):

1
2
#!/bin/bash
echo "\"Hello World\" !" > /usr/test.txt

删除日志的一份 Shell 脚本,当前路径在 s 下,然后要删除 abc 下的 log:

1
/s/a     /s/b     /s/c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#!/bin/bash
# 定义变量folders
# ()是数组
folders=(a,b,c)
# 使用${folders}引用变量
# 逻辑循环
for file in ${folders[*]}
do
cd ${file}
for subfile in ./*
do
# test -d:检测是否是文件 (shell-test命令参考: https://www.cnblogs.com/guanyf/p/7553940.html)
if test -d $subfile
then
name=${subfile##*/}
# echo -e:激活转义(echo详细解释: https://blog.csdn.net/preamble_1/article/details/72900129)
# 显示当前文件路径名称
echo -e "\033[35m[$name]\033[0m"
cd $name/log
rm -rf $(find . -name "*.log")
cd ../../
fi
done
cd ..
done

时间格式化

1
2
3
4
5
6
7
last_date=`date -d last-day +%Y%m%d`
last_date_dfs=`date -d last-day +%Y-%m-%d`
cur_date=`date +%Y%m%d`
cur_date_dfs=`date +%Y-%m-%d`

cur_datetime=`date +%Y%m%d %H%M%S`
...

Shell 中单引号和双引号区别

  1. /home/atguigu/bin 创建一个 test.sh 文件:
1
vim test.sh
  1. 在文件中添加如下内容:
1
2
3
4
5
6
7
#!/bin/bash
do_date=$1
echo '$do_date'
echo "$do_date"
echo "'$do_date'"
echo '"$do_date"'
echo `date`
  1. 查看执行结果:
1
2
3
4
5
6
test.sh 2019-02-10
$do_date
2019-02-10
'2019-02-10'
"$do_date"
2019年 05月 02日 星期四 21:02:08 CST

总结:

  • 单引号不取变量值
  • 双引号取变量值
  • 反引号 `,执行引号中命令
  • 双引号内部嵌套单引号,取出变量值
  • 单引号内部嵌套双引号,不取出变量值

Shell 脚本中判断输入变量或者参数是否为空的方法

方法一:判断变量

1
2
3
4
5
6
read -p "input a word :" word
if [ ! -n "$word" ] ;then
echo "you have not input a word!"
else
echo "the word you input is $word"
fi

方法二:判断输入参数

1
2
3
4
5
if [ ! -n "$1" ] ;then
echo "you have not input a word!"
else
echo "the word you input is $1"
fi

方法三:直接通过变量判断

1
2
3
4
5
if [ ! $xxx ]; then
echo "IS NULL"
else
echo "NOT NULL"
fi

方法四:使用 test 判断

得到的结果就是: dmin is not set!

1
2
3
4
5
6
if test -z "$xxx"
then
echo "dmin is not set!"
else
echo "dmin is set !"
fi

方法五:使用 "" 判断

1
2
3
4
5
6
if [ "$xxx" = "" ]
then
echo "dmin is not set!"
else
echo "dmin is set !"
fi

Shell 中的 ${}##%% 的使用

假设我们定义了一个变量为:

1
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

字符串长度:

  • ${#var} 可计算出变量值的长度
  • ${#file} 可得到 27,因为 /dir1/dir2/dir3/my.file.txt 是 27 个字节

去掉最后/最前一个字符

1
2
3
4
5
# 去除字符串的首字符
${str:1}

# 去除字符串的最后一个字符
${str%?}

有下面三种方式实现去除最后一个字符:

1
2
3
sed 's/.$//'
awk '{sub(/.$/,"")}1'
awk '{printf $0"\b \n"}' ufile

Shell 的加减乘除

1
2
3
4
5
6
i=0
# 二次为i进行赋值
((i=$j+$k)) # 等价于 i=`expr $j + $k`
((i=$j-$k)) # 等价于 i=`expr $j -$k`
((i=$j*$k)) # 等价于 i=`expr $j \*$k`
((i=$j/$k)) # 等价于 i=`expr $j /$k`

expr 不支持得到有小数点的除法,如果结果可能得到小数,可以使用 bc 工具,scale 控制小数点后保留几位:

1
2
num3=`echo "scale=2; $num1/$num2" | bc`
echo "num1/num2=$num3"