Shell函数
位置参数和特殊变量
$0 相当于C语言main函数的argv[0]
$1、$2... 这些称为位置参数(Positional Parameter),相当于C语言main函数的argv[1]、argv[2]...
$
$@ 表示参数列表"$1" "$2" ...,例如可以用在for循环中的in后面。
$* 表示参数列表"$1" "$2" ...,同上
$? 上一条命令的Exit Status
$$ 当前进程号
#!/bin/bash
echo "before shift"
echo '$0:' $0
echo '$1:' $1
echo '$2:' $2
echo '$3:' $3
echo '$4:' $4
echo '$5:' $5
echo '$#:' $
echo '$@:' $@
echo '$*:' $*
echo '$$:' $$
shift
echo "after shift"
echo '$0:' $0
echo '$1:' $1
echo '$2:' $2
echo '$3:' $3
echo '$4:' $4
echo '$5:' $5
echo '$#:' $
echo '$@:' $@
echo '$*:' $*
echo '$$:' $$
加法器脚本
#!/bin/bash
sum=0
while [ -n "$1" ]
do
sum=$[$sum+$1]
shift
done
echo $sum
echo $11
输入输出
echo [option] string
-e 解析转义字符
-n 不回车换行。默认情况echo回显的内容后面跟一个回车换行。
echo "hello\n\n"
echo -e "hello\n\n"
echo "hello"
echo -n "hello"
管道
cat myfile | more
ls -l | grep "myfile"
df -k | awk '{print $1}' | grep -v "文件系统"
df -k 查看磁盘空间,找到第一列,去除“文件系统”,并输出
标准错误输出不会重定向
tee
tee命令把结果输出到标准输出,另一个副本输出到相应文件
df -k | awk '{print $1}' | grep -v "文件系统" | tee a.txt
tee -a a.txt表示追加操作
df -k | awk '{print $1}' | grep -v "文件系统" | tee -a a.txt
文件重定向
cmd > file 把标准输出重定向到新文件中
cmd >> file 追加
cmd > file 2>&1 标准出错也重定向到1所指向的file里 (1,2都是文件描述符)
cmd >> file 2>&1
cmd < file1 > file2 输入输出都定向到文件里
cmd < &fd 把文件描述符fd作为标准输入
cmd > &fd 把文件描述符fd作为标准输出
cmd < &- 关闭标准输入
函数
#! /bin/sh
foo(){ echo "Function foo is called";}
echo "-=start=-"
foo
echo "-=end=-"
#!/bin/bash
testfunc()
{
echo "Testfunc"
return 1
}
testfunc
echo $?
testfunc2()
{
echo "aaaaa"
return 0
}
var=`testfunc2`
echo $var
#! /bin/sh
is_directory()
{
DIR_NAME=$1
if [ ! -d $DIR_NAME ]; then
return 1
else
return 0
fi
}
for DIR in "$@"; do
if is_directory "$DIR"
then :
else
echo "$DIR doesn't exist. Creating it now..."
mkdir $DIR > /dev/null 2>&1
if [ $? -ne 0 ]; then
echo "Cannot create directory $DIR"
exit 1
fi
fi
done
遍历目录
#!/bin/bash
function visit
{
local dir="$1"
for f in `ls $dir`
do
if [ -f "$dir/$f" ]
then
echo "$dir/$f is a file"
elif [ -d "$dir/$f" ]
then
echo "$dir/$f is a dir"
visit "$dir/$f"
else
echo "$dir/$f is not recognized"
fi
done
}
visit .
Shell脚本调试方法
Shell提供了一些用于调试脚本的选项,如:
-n 读一遍脚本中的命令但不执行,用于检查脚本中的语法错误。
-v 一边执行脚本,一边将执行过的脚本命令打印到标准错误输出。
-x 提供跟踪执行信息,将执行的每一条命令和结果依次打印出来。
打开调试的方法
命令行提供参数 bash -x xxx.sh
脚本开头输入
在脚本里面显示输入 set -x
正则表达式
1 以S开头的字符串
^S
2 以数字结尾的字符串
[0123456789] 匹配任意数字
[0-9]
\d
$ 匹配字符串结尾
[0-9]$
3 匹配空字符串(没有任何字符)
^$
4 字符串只包含三个数字
^\d\d\d$
^\d{3}$
{n} 花括号括起来一个数字,表示前面的单元重复n次
5 字符串只有3到5个字母
控制最少重复次数和最大的重复次数
{m,n} m表示前面单元最小重复次数,n表示最大重复次数
[a-zA-Z] 表示大小写字母 如果中括号中有多个区间,区间之间不要留空格或其他分隔符
^[a-zA-Z]{3,5}$
6 匹配不是a-z的任意字符
[^a-z] 中括号中第一个字符如果是^,表示区间取反
^[^a-z]$
7 字符串有0到1个数字或者字母或者下划线
{0,1} 表示重复0-1次
? 也可以表示0-1次重复
^[0-9a-zA-Z_]?$
^\w?$
8 字符串有1个或多个空白符号(\t\n\r等)
\s 表示空白字符 包括 \t\n\r ....
{1,} 表示重复1-n 跟+号一样
^\s+$
9 字符串有0个或者若干个任意字符(除了\n)
. 代表任意字符,除了\n
^.{,}$ 花括号中两个参数置空表示重复次数任意 0-n
^.*$ *表示前面的单元重复0-n次
? 0-1
+ 1-n
* 0-n
10 匹配0或任意多组ABC,比如ABC,ABCABCABC
使用小括号来讲多个单元重新组合成为一个单元
^(ABC)*$
11 字符串要么是ABC,要么是123
| 表示选择,选择两边的正则匹配一个
^ABC$|^123$
^(ABC|123)$ 小括号也可以将选择范围控制在括号内
12 字符串只有一个点号
做转义 还是使用\
^\.$
13 匹配十进制3位整数
100 - 999
^[1-9][0-9]{2}$
匹配十进制 0-999 的数字
分段
一位数
[0-9]
两位数
10-99
[1-9][0-9]
三位数
[1-9][0-9]{2}
^([0-9]|[1-9][0-9]{1,2})$
14 匹配0-255的整数
匹配 ip
分段
一位数
[0-9]
两位数
10-99
[1-9][0-9]
三位数
100-199
1[0-9]{2}
200-249
2[0-4][0-9]
250-255
25[0-5]
^([0,9]|[1,9][0,9]|1[0,9]{2}|2[0,4][0,9]|25[0,5])
15 匹配端口号
0-65535
16 email
[\w!
基础的正则
+?* 是普通字符
扩展的正则
+?* 是特殊字符
perl的正则
最常用
perl正则在扩展正则之上添加了一些特殊符号
\d \w \s ....
sort
命令从标准输入中读取数据然后按照字符串内容进行排序
-f 忽略字符大小写
-n 比较数值大小
-t 指定分割符,默认是空格或者tab
-k 指定分割后进行比较字段
-u 重复的行只显示一次
-r 反向排序
-R 打乱顺序
同样的两行洗不乱
将/etc/passwd 根据用户id来排序
sort -t: -k3 -n < /etc/passwd
uniq
去除重复的行,前提是重复的行连续
-c 显示每行重复的次数
-d 仅显示重复过的行
-u 仅显示不曾重复的行
sort < test.txt | uniq
wc word count 查看行数
-l 统计行数
-c 统计字节数
-w 统计单词数
grep global regular expression print
-c 只输出匹配行的计数
-i 不区分大小写
-H 文件名显示
-r 递归遍历目录
-n 显示行号
-s 不显示不存在或无匹配文本的错误信息
-v 显示不包含匹配文本的所有行,这个参数经常用于过滤不想显示的行(反选)
-E 使用扩展的正则表达
-P 使用perl的正则表达式
-F 匹配固定的字符串,而非正则表达式
egrep = grep -E
fgrep = grep -F
rgrep = grep -r
grep 默认使用的是基础的正则
find
find pathname -options [-print -exec -ok ...]
option 选项如下:
-name 按照文件名查找文件。
find . -name "1.txt"
-perm 按照文件权限来查找文件。
find . -perm 660
-user 按照文件属主来查找文件。
-group 按照文件所属的组来查找文件。
-mtime -n +n 按照文件的更改时间来查找文件,-n表示文件更改时间距现在n天以内,+n表示文件更改时间距现在
n天以前。find命令还有-atime和-ctime 选项,但它们都和-m time选项。
-atime 访问时间
-ctime 创建时间
-nogroup 查找无有效所属组的文件,即该文件所属的组在/etc/groups中不存在。
-nouser 查找无有效属主的文件,即该文件的属主在/etc/passwd中不存在。
-newer file1 ! file2 查找更改时间比文件file1新但比文件file2旧的文件。
-type 查找某一类型的文件,诸如:
b - 块设备文件。
d - 目录。
c - 字符设备文件。
p - 管道文件。
l - 符号链接文件。
f - 普通文件。
s - socket文件
-exec
find . -name "*.txt" -exec gzip {} \;
查找当前目录下的txt文件并且打包成为gzip
每找到一个文件,就会执行exec后面的命令
gzip ./a/2.txt
gzip ./a/6.txt
最后是一个\; 反斜杠不能省,作为当前exec后面命令的结束符
-ok
跟-exec用法一样,但是每找到一个文件要执行后面的命令前会给用户确认
xargs
将标准输入的参数整齐的拼凑在一行里边 单独使用该命令没什么用,要配合其他命令来使用
docker ps -aq | xargs docker rm -f
find . -name "*.txt" | xargs -I{} mv {} xxx/
-I{} 指定一个替换字符串作为参数替换
sed
文本1 -> sed + 脚本 -> 文本2
ed 编辑器 -> sed -> vim
sed option 'script' file1 file2 ... sed 参数 ‘脚本(/pattern/action)’ 待处理文件
sed option -f scriptfile file1 file2 ... sed 参数 –f ‘脚本文件’ 待处理文件
sed -n '2p' test.txt 打印出txt里面的第二行
sed '/123/d' test.txt 匹配123并删除
p, print 打印
a, append 追加
i, insert 插入
d, delete 删除
s, substitution 替换
awk
awk option 'script' file1 file2 ...
awk option -f scriptfile file1 file2 ...
最常见用法就是过滤哪一列
xxxx | awk '{print $2}'
cat /etc/passwd | awk -F: '{print $3}' 过滤打印/etc/passwd里面的第三列(也就是id)
脚本格式
{actions}
每一行文本都无条件的执行脚本
/pattern/{actions}
匹配了模式之后再执行后面的动作
condition{actions}
BEGIN
在遍历文本的第一行之前会执行某个动作
END
在遍历完文本之后再去执行某个动作
// xxx.txt
ProductA 30
ProductB 76
ProductC 55
在输出表格之前输出表头 产品名字 库存
输出完表格之后 输出 库存总量 : xxxx
在遍历之前输出表头
BEGIN{
printf "%s\t%s\n","产品","库存";
sum=0;
}
在遍历每一行的过程中输出每一行的内容,将库存加到sum变量
{
printf "%s\t%s\n",$1,$2;
sum+=$2;
}
遍历完之后输出sum变量
END{
printf "库存总量:%d\n",sum
}
crontab 定时器
linux 系统定时器
需求,每天什么时候去做什么事情
/etc/crontab
17 * * * * root cd / && run-parts --report /etc/cron.hourly
25 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
|