shell脚本--常用知识

hello world!
#! /bin/bash
echo “hello world!”

$ chmod +x a.sh
$ ./a.sh
hello world!



变量
变量不分类型 (没有int,char,string)
不需要声明,直接使用
赋值:name=value (左右两边不能有空格)
使用:$name ${name}


foo=h
echo ${foo}ello


变量的作用域
默认全局作用域(仅当前shell可见)
local 限定函数局部变量
function a() { local msg; }
使用export导出变量,让子shell可以继承
export var=1
source 或 .(dot) 在当前shell下执行脚本
source ./config.sh


变量分类
自定义变量
环境变量 (set命名可查看)
$PATH,$IFS,$PS1,$PWD,$LINENO
位置参数(Positional Parameters)
$1 $2 $3 … ${10}
特殊参数(Special Parameters)
$#:位置参数的数量
$*:所有位置参数的内容 ($1 $2 …)
$@: 所有位置参数的内容(“$1” “$2” … )
$?:命令执行后返回的状态
$$:当前进程的进程号
$!:后台运行的最后一个进程号
$0:当前执行的进程名


玩转变量
使用eval实现变量的间接引用
x='abc def'
y='$x'
echo $y
$x
eval echo $y
abc de




玩转变量(续)
${!p} #双重引用
a=1
b='a'
echo ${!b}
1
${!p*} #返回所有以p开头的变量
echo ${!P*}
PATH PIPESTATUS PPID PS1 PS2 PS4 PWD
${p:-word} #如果变量p不存在,返回"word”
${p:=word} #如果变量p不存在,返回"word",并将p的值设为"word"
${p:?word} #如果变量p不存在,将"word"打入STDERR
${p:+word} #如果变量p存在,返回"word"


玩转变量(续)
if [${ret:=1} -ne 0 ]
then
echo “NO”
exit
fi



引号迷雾
双引号

使用双引号可解释$符号,反引号和反斜线等特殊字符
echo “$msg” => 显示msg变量值
单引号
与双引号类似,不同的是shell会忽略任何特殊符号
echo ‘$msg’ => 显示$msg
反斜杆
\c == ‘c’
反引号(命令替换)
用于执行系统命令并输出到变量
echo The date and time is `date` 


几种括号
(list) list将在一个子shell中执行, 不会对当前shell产生影响,返回list的exit值
{ list; } 可以作组合命令用,list将在当前shell中被执行,list结尾处必须要有新行或‘;’号,返回list的exit值,list前后必须有空格
((expression)) 算术计算
[ ] [[ ]] 分支测试


数组
name=(value1 ... valuen) 此时下标从0开始
name[index]=value
unset name 或 name=

数组下标的范围没有任何限制,同时也不必使用连续的分量
$ A=(a b c def)
$ A[3]=bb

$ echo ${A[0]} #取第一个元素
a
$ echo ${A[@]} # 取全部元素
a b c def
$ echo ${#A[@]} # 取得数组元素的个数
4



数组(续)
遍历数组:
total=${#A[*]}
for ((i = 0; i < total; i++))
do
echo ${A[$i]}
done



分支语句
if list; then command;
[ elif list; then command; ] ...
[ else command; ]
fi
case $word in
[a-z]) list ;;
*) default;;
esac
[ $# -eq 1 ] && slen=1 || slen=0



条件测试
对文件、字符串和数字使用test命令。test一般有两种格式:
test condition 或 [ condition ](注意空格)
if [ $str = “a.txt” ];then
echo “OK"
fi
直接测试命令:
if grep abc a.txt &>/dev/null;then
echo “Bingo!”
fi




条件测试(续)
推荐使用[[ ]]进行条件测试
if [[ “x$str”== “xa.txt” && -f b.txt ]]
then
cmd;
fi
-f -d -z ……
man bash
CONDITIONAL EXPRESSIONS



条件测试 – 数值比较
if [ $a –lt 0 ]
then
echo OK
fi

推荐使用(( ))
if (( a > 0 ))
then
echo OK
fi



循环语句
for name [ in word ] ; do list ; done
for i in `ls *.result`;do cat $i; done

for (( expr1 ; expr2 ; expr3 )) ; do list ;done
for ((i=0;i<100;i++));do echo $i;done

while list; do list; done
while read line
do
echo $line
done < a.txt
until list; do list; done



注释
# 行注释 (#前要有空格)
echo $msg #print message

块注释
:<<COMMENT
echo $msg
COMMENT

comment()
{
echo $msg
}


正则表达式基础
元字符
. 匹配任何单个字符。
 $ 匹配行结束符。^ 匹配一行的开始。
* 匹配0或多个正好在它之前的那个字符。
+ 匹配1或多个正好在它之前的那个字符。
? 匹配0或1个正好在它之前的那个字符。
\{i\} \{i,j\} 匹配指定数目的字符。
\ 这是引用符,转义;
[ ]  [c1-c2] 匹配括号中的任何一个字符。 [^c1-c2]
\< \> 匹配词(word)的开始(\<)和结束(\>)。
\( \) 将 \( 和 \) 之间的表达式定义为“组”(group),并且将匹配这个表达式的字符保存到一个临时区域(一个正则表达式中最多可以保存9个),它们可以用 \1 到\9 的符号来引用。
| 将 两个匹配条件进行逻辑“或”(Or)运算。例如正则表达式(him|her)



正则表达式举例
HTML标签
<[^>]*>

匹配由26个英文字母组成的字符串
^[A-Za-z]+$
  
Email地址
\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*

URL
[a-zA-z]+://[^\s]*



管道和重定向
管道可以把一条命令的输出作为另一条命令的输入
Command1 | Command2
返回值是最后一个命令的返回值

重定向
wc –l /etc/passwd > a.txt
wc –l /etc/passwd >> a.txt
wc –l < /etc/passwd
./command > a.txt 2>&1 (./command &> a.txt)

exec 5<> a.txt
echo “hello” >&5
<&-
>&-


作业控制
<CTRL-Z> 将当前任务挂起,返回job_id
fg job_id 把后台作业放到前台执行
bg job_id 把作业放到后台执行

vi b.sh
<CTRL-Z>
[1]+ Stopped vim b.sh
bg 1
[1]+ vim b.sh &
fg 1
vim b.sh


自定义函数
function foo() # foo为函数名
{
local a=$1; # 局部变量

echo $a;
return 0; # 返回值
}

foo “cool!” # 函数调用
echo $? # 打印返回值



自定义函数 – 16进制转点分十进制
a()
{
       local str=$1
       echo -n $((16#${str:0:2}))
       str=${str:2}
       if [ "x$str" = "x" ]
       then
              echo; return
       else
              echo -n "."; a $str
       fi
}
#Usage
a "DDB14CCF"


整数计算
id++ id-- ++id –id - + ! ~ ** * / % 计算
<< >> & ^ | 位操作
<= >= < > == != 比较
&& || 逻辑操作
expr?expr:expr 三元操作符
= *= /= %= += -= <<= >>= &= ^= |= 赋值操作符

y=2000 闰年计算
echo  $((y%4==0 && y%100!=0 || y%400==0))
(( y++ )) 自增1
tmp=$((16#a)) 进制转换


浮点运算
echo “scale=5; 3/7"|bc –l
.42857
echo "100.43KB 20.12KB" | awk '{print $1-$2}'
80.31
echo "ibase=16;F"|bc -l
15




简单字符串处理
x=abcd
${#x} # 获取字串长度
4
expr index  $x “b“ # 获取子串所在偏移
2expr index  $x "a“ # 获取子串所在偏移
1
echo ${x:1} # 获取子串
bcdecho ${x:2}cdecho ${x:0:2}
ab



简单的字符串处理(续)
x=aabbaarealwwvvwwecho “${x%w*w}“ # 截去尾部最短匹配
aabbaarealwwvvecho “${x%%w*w}“ # 截去尾部最长匹配
aabbaarealecho “${x##a*a}“ # 截去头部最长匹配
lwwvvwwecho “${x#a*a}“ # 截去头部最短匹配
bbaarealwwvvww

x=abcdabcdecho ${x/a/b} # 只替换一个bbcdabcdecho ${x//a/b} # 替换所有bbcdbbcd


简单字符串处理 – 实际应用
截去域名尾部
name=jx-sys-superdb.jx.baidu.com
echo ${name%%.*}
jx-sys-superdb

截取日期
str=20081011
year=${str:0:4}

替换
echo ${name//jx/tc}
tc-sys-superdb.tc.baidu.com


随机字符串生成
typeset -r DEFAULT_STR_LEN=5
typeset -ra dict=(a b c d e f g h i j k l m n o p q r s t u v w x y z)

function get_random_letter()
{
echo -n ${dict[$((RANDOM%${#dict[*]}))]}
return 0
}

function get_random_string()
{
local slen str

[ $# -eq 1 ] && slen=$1 || slen=$DEFAULT_STR_LEN

for ((i = 0; i < slen; i++))
do
str=${str}`get_random_letter`
done

echo $str
return 0
}

get_random_string $1


调试
-x
-n 是只语法检查而不执行任何命令
-e 是脚本发生第一个错误时就中止脚本运行,即当一个命令返回非零值时退出脚本 (除了until 或 while loops, if-tests, list constructs)
--posix 是更改Bash或脚本的行为,使之符合POSIX标准
Shell 伪信号:EXIT,ERR,DEBUG


调试(续)
+ typeset -r DEFAULT_STR_LEN=5
+ typeset -ra 'dict=(a b c d e f g h i j k l m n o p q r s t u v w x y z)'
+ get_random_string 2
+ local slen str
+ '[' 1 -eq 1 ']'
+ slen=2
+ (( i = 0 ))
+ (( i < slen ))
++ get_random_letter
++ echo -n t
++ return 0
+ str=t
+ (( i++ ))
+ (( i < slen ))
++ get_random_letter
++ echo -n k
++ return 0
+ str=tk
+ (( i++ ))
+ (( i < slen ))
+ echo tk
tk
+ return 0

信号捕获
#!/bin/bash

trap "print_OK" 3

function print_OK()
{
echo OK
}

while :
do
:
done

发送信号:kill -3 pid

屏蔽信号:trap “” 3


其他常用内置命令
exec command #用command替换当前进程
type ls
ls is aliased to `ls --color=tty`
: 空命令
while :
do
cmd
done

if [ list ]; then : ;else echo false;fi


常用工具
编辑软件: vi,emacs
联机帮助:man, info
查找类:find,locate,which,whereis,whatis
文本处理类:uniq,cut,paste,join,sort,comm,diff
二进制文件读取类:od,xxd,dd,hexdump
文本分析类:grep,sed,awk
系统状态类:top,ps,pstree,pgrep,/proc,strace,vmstat,netstat
传输类:wget



Grep - 全文匹配利器
--color 飘红匹配到的部分
-i 忽略大小写
-v 反向匹配
-r 递归匹配文件
-o 只打印匹配到的部分
-n 打印出行号
-c 统计匹配到的行数
-w 匹配整词

grep "sort“ *.doc

Awk – 文本处理利器
awk命令的一般形式: awk ' BEGIN { actions } pattern1 { actions } ............ patternN { actions } END { actions } ‘
awk -F: '{print $1} END{print "total:",NR}' /etc/passwd



Awk – 文本处理利器 (续)
取机器序列号
dmidecode|awk '/Serial Number:/{print $NF;exit}‘

统计词频
awk '{a[$0]++}END{for(i in a){print i,a[i]}}' a.txt

类似uniq功能
awk '! a[$0]++' a.txt



Awk – 文本处理利器 (续)
杨辉三角
#!/usr/bin/awk -fBEGIN {         yan[1,0] = 1;         for (i = 2; i <= int(ARGV[1]); i++)         {                 yan[i,0] = 1;                 yan[i,i-1] = 1;                                 for (j = i-2; j > 0; j--)                         yan[i,j] = yan[i-1,j-1] + yan[i-1,j]         }                 # output         for (i = 1; i <= int(ARGV[1]); i++)         {                 for (j = 0; j < i; j++)                         printf("%d ", yan[i,j]);                 print         }}
#Usage:
#     $ ./test.awk 10


head,tail
功能:取一个文件的头若干行或者尾部的若干行。
常用选项:
-n num:指定选取的行数
-f:tail的选项,定时输出文件的最后若干行。
使用举例
tail和head常用来分析日志或者对大规模数据抽取一小部分
tail –f example.log
watch -n 1 head url.lst



diff,cmp,diff3,sdiff,comm
功能:
diff:按行比较两个文件的不同
cmp:按字节比较两个文件的不同
diff3:按行比较三个文件的不同
sdiff:输出两个文件的合集。输出文件中两个文件原本的行在同一行中不同列
comm:快速的比较两个已经排过序的文件,输出两个文件的合集,交集,或任何单独的部分



diff常用选项
常用选项。主要介绍diff的各个选项
-b 忽略两行行尾空格,以及空格个数的区别
-E 忽略tab和空格间的区别
-w 完全忽略所有空格类字符
-B 忽略空行
-I 忽略大小写
--normal以normal形式输出不同行。即指输出不同的行
-c 以context形式输出不同行。包含不同行的上下文



find,locate
功能:查找文件。find将在目录树中查找和用户指定模式相符合的文件。locate则是通过在locate的数据库中查找,locate 的数据库由updatedb程序负责维护。
常用选项:
-name:指定要查找的文件名
-perm:指定要查找文件的权限
-size:指定要查找文件的大小范围
-mtime:指定查找修改时间在n天以内的文件。
exec command:将find命令查找到的文件作为command命令的参数
使用举例:
find . -mtime –1:查找在最近一天内被修改的文件
find . -name b.cpp -exec mv \{\} a.cpp \;





sort
功能:对文件中的各行进行排序。
sort排序是根据从输入行抽取的一个或多个关键字进行比较来完成的。缺省情况下以整行为关键字按ASCII字符顺序进行排序。
常用选项
- m 若给定文件已排好序,合并文件。
- c 检查给定文件是否已排好序。
- u 对排序后认为相同的行只留其中一行。
- d 按字典顺序排序,仅比较字母、数字、空格和制表符。
- r 按逆序输出排序结果。
- b 在每行中寻找排序关键字时忽略前导的空格和制表符。
- t separator 指定字符separator作为字段分隔符。
-k,pos1,[pos2]:以pos1到pos2中间的字符为键值
使用举例
cat words | uniq –c | sort –k 1,1 –n –r 将一批词按照出现频次有高到低排序



uniq,join,cut,paste
cut功能:用来从标准输入或文本中剪切指定列或者域
常用选项:
-c:指定剪切字符数
-f:field 指定剪切指定域数
-d:delimit 指定除空格和tab外的域分隔符
使用举例:
cut –d : -f 3 example.txt
who –u|cut –c1-8
paste功能:将两个文件按行粘贴在不同的列中。是cut的反向操作。



dd
拷贝二进制文件,
格式:
count=BLOCKS 只拷贝BLOCKS个数据块
ibs=BYTES 一次读入的数据量
if=FILE 输入文件
obs=BYTES 一次写出的数据量
of=FILE 输出文件
seek=BLOCKS 输出文件跳过BLOCKS个数据块
skip=BLOCKS 输入文件跳过BLOCKS个数据块

time dd if=/dev/zero of=test bs=1024k count=1024 查看系统io性能


wget
功能:支持使用FTP和HTTP协议,从其他主机上下载所需要的文件
常用选项:
-r:递归的下载目录以及它的子目录和所有文件
-nH:不创建以目标主机域名为目录名的目录,将目标主机的目录结构直接下到当前目录下
--cut-dir=[number]不在本地机器上建立的目录层数
-m, --mirror自动开启适合用来镜像站点的选项
-A, --accept=LIST允许下载的文件类型列表
-R, --reject=LIST拒绝继续下载的文件类型列表
-D, --domains=LIST允许继续扩展的站点列表
--tries=[number]自动重连的次数
-c:断点续传
--debug:使用这个选项可以看到更多wget下载文件过程中的调试信息,比如下载一个http文件时所发送和接收的http包头的格式
--timeout=SECONDS控制wget读超时时间,缺省为900秒
Wget –nH –cut-dir=1 ftp://*:*@test.baidu.com/
wget “http://www.sina.com”




参考资料
Man
正则表达式之道
Sed与awk
Advanced Bash-Scripting Guide

你可能感兴趣的:(shell脚本,常识)