本篇文章,你可以把它当做shell的入门教程来学习,你也可以把它当做shell学习的大纲,对应这里的每一个知识点进行更深入的学习(查资料或者看书),对于不是专业的Linux运维人员来说<<Linux shell 脚本攻略>>和<<Linux 命令行大全>>这两本书足够应付日常使用Linux的大部分问题.
在这里附上学习shell时的小例子:https://github.com/newbietao/shell_study
较为有用的shell脚本实例:https://github.com/newbietao/happy_shell
一、变量
1.声明变量:
var_name=value,注意等号两边没有空格
2.引用变量:
在使用变量时要在变量前面加$,例如:
str="hello world"
echo $str
3.常用的系统变量:
$PATH:执行Linux命令时的查找路径
$HOME:当前用户的家目录
$PWD:当前路径
$USER:当前用户
$UID:当前用户id
$RANDOM:随机数
4.变量的扩展
${#var_name}:变量var_name的长度
${var_name:-hello}:当${变量}未定义或为空值时,使用字符串作为返回值
${var_name:+hello}:当${变量}为非空值时,使用字符串作为返回值
${var_name:=hello}:当${变量}为未定义或为空值时,使用字符串作为返回值,同时赋值给${变量}
5.位置变量:
$0:命令本身
$1:命令或者函数的第一个参数
$2:命令或者函数的第二个参数
$n:以此类推
6、其他变量
$#:参数的个数
$*:全部参数
$@:全部参数
$?:最后一条命令的返回值
$!:最后一条后台执行的命令的PID值
二、字符串
1.定义:
Linux里面的字符串可以直接写,不用加单引号和双引号,但是如果字符串里面包含空格就需要加双引号或者单引号,双引号可以将变量进行扩展。
str=hello
echo $str #hello
str="hello world"
echo $str # hello world
2.长度
str="hello"
echo ${#str} # 5
3. 截取
规则1:${变量名:位置起点}
含义:由指定的位置起点开始,截取子字符串到字符串结束,起点由0开始
例1:
var="12345678"
echo ${var:5}
输出:678
-------------------------------
规则2:${变量名:位置起点:长度}
含义:由指定的位置起点开始,截取指定长度的字符串,起点由0开始
例2:
var="12345678"
echo${var:0:5}
输出:12345
4.替换
规则1:${变量/样式/替换字符串}
含义:如果变量中有符合样式的字符串,则使用替换字符串替代,只替换第一个符合样式的字符串
例1:
var="12341234"
echo ${var/1234/1111}
输出:11111234
-------------------------------
规则2:${变量//样式/替换字符串}
含义:如果变量中有符合样式的字符串,则使用替换字符串替代,替换全部符合样式的字符串
例1:
var="12341234"
echo ${var//123/}
输出:44
5.对比样式,提取文件名或者文件后缀
规则1:${变量#样式}
含义:表示由变量值的最左边开始与样式进行对比,删除"最短相符合的字符串"
例1:
var="12345678"
echo ${var#*3}
输出:45678
-------------------------------
规则2:${变量##样式}
含义:表示由变量值的最左边开始与样式进行对比,删除"最长相符合的字符串"
例2:
var="12341234"
echo ${var##*3}
输出:4
-------------------------------
规则3:${变量%样式}
含义:表示由变量值的最右边或最后边开始与样式进行对比,删除"最短相符的字符串"
例3:
var="12341234"
echo ${var%3*}
输出:123412
-------------------------------
规则4:${变量%%样式}
含义:表示由变量值的最右边或最后边开始与样式进行对比,删除"最长相符的字符串"
例4:
var="12341234"
echo ${var%%3*}
输出:12
6.拼接
str=hello
echo "$str world"
输出:hello world
三、数字计算
1.整数
方法一:
num1=12
num2=23
let num=num1+num2
echo $num # 35
方法二:
num1=12
num2=23
num=$((num1+num2))
echo $num # 35
2.强大的计算器,bc是一个强大的计算器:
http://man.linuxde.net/bc
echo "12 + 23" | bc
四、数组
1.定义数组
// 直接声明
arr1[0]=hello
arr1[1]=world
arr1["first"]=one # 关联数组
//
declare
关键字声明;
declare
-A arr2
arr2[0]=hello
arr2[1]=world
// 使用()进行声明
arr3=(aa bb cc)
arr3=([first]="aa" [two]="bb") # 关联数组
2.访问和删除数组元素
arr=(11 22 33)
echo ${arr[0]} # 11 访问数组元素
unset arr[0]
echo ${arr[0]} # 空
unset arr #删除整个数组
3.数组长度,数组全部元素,数组全部下标
arr=(11 22 33)
echo ${#arr[*]} # 3 长度
echo ${arr[*]} # 11 22 33 全部元素
echo ${arr[@]} # 11 22 33 全部元素
echo ${!arr[*]} # 0 1 2 全部下标
4.提取数组元素,替换数组元素
提取和替换同字符串是一样的
arr=(11 22 33)
echo ${arr[*]/22/44} # 将22替换成44
echo ${arr[*]:1:1} # 22 输出数组从第二个位置开始长度为1的元素
5.遍历数组
arr=(11 22 33)
for (( i=0; i<${#arr[*]; i++}));do
echo ${arr[$i]}
done
for var in ${arr[*]};do
echo $var
done
五、函数
1.函数声明:
function fun_name() {
echo "hello world"
}
或者
fun_name() {
echo "hello world"
}
2.传递参数
function fun_name(){
echo $1
}
fun_name "hello world"
3.作用域:在函数里面用location 声明的变量是局部变量,其他的变量都是全局变量
#!/bin/bash
str="hello world"
function sayHello(){
local str
str="hello linux"
echo $str
}
sayHello
echo $str
4.递归调用fork炸弹:
:(){
: || : &
}
:
六、条件分支
1.if
if test;then
# 当test为真,执行这里的语句
elif test;then
# 当第一条test为假,第二条test为真时,执行这里的语句
else
# 当前两个test都为假时,执行这里的语句
fi
2.test
test命令推荐写成[[ ]],切记双中括号的内部左右各有一个空格
1 字符串判断
[[ str1 = str2 ]] 当两个串有相同内容、长度时为真
[[ str1 != str2 ]] 当串str1和str2不等时为真
[[ -n str1 ]] 当串的长度大于0时为真(串非空)
[[ -z str1 ]] 当串的长度为0时为真(空串)
[[ str1 ]] 当串str1为非空时为真
2 数字的判断
[[ int1 -eq int2 ]] 两数相等为真
[[ int1 -ne int2 ]] 两数不等为真
[[ int1 -gt int2 ]] int1大于int2为真
[[ int1 -ge int2 ]] int1大于等于int2为真
[[ int1 -lt int2 ]] int1小于int2为真
[[ int1 -le int2 ]] int1小于等于int2为真
3 文件的判断
[[ -r file ]] 用户可读为真
[[ -w file ]] 用户可写为真
[[ -x file ]] 用户可执行为真
[[ -f file ]] 文件为正规文件为真
[[ -d file ]] 文件为目录为真
[[ -c file ]] 文件为字符特殊文件为真
[[ -b file ]] 文件为块特殊文件为真
[[ -s file ]] 文件大小非0时为真
[[ -t file ]] 当文件描述符(默认为1)指定的设备为终端时为真
3 复杂逻辑判断
-a 与
-o 或
! 非
[[ -s file -a -r file ]] 文件大小非0且可读时为真
[[ -s file ]] && [[ -r file ]] 文件大小非0且可读时为真
3.case
语法:
var = xxx
case $var in
value1 )
echo "input is value1"
;;
value2 )
echo "input is value2"
;;
valuen )
echo "input is valuen"
;;
* )
echo "i don't know"
;;
esac
说明:
1、星号(*)相当于其他语言中的default;
2、双分号(;;)是必须的,相当于java中的break;
3、竖线(|)用于分割多个模式,相当于or;
原理:
首先对$var进行运算,然后将运算的值与case语句中的各个值匹配,执行相匹配的语句
七、循环
1.for
for ((i=0; i<10; i++));do
echo $i
done
arr=(11 22 33)
for var in ${arr[@]};do
echo $var
done
说明:
for in 可以遍历用IFS分割的字符串:"haha hehe kaka",数组: ${arr[*]},扩展:{1..9},目录: ./*
2.while
num=0
while [[ $num -lt 10 ]];do
echo $num
num=$((num + 1))
done
3.遍历目录
path="./*"
for var in $path;do
echo $var # 输出制定路径下的所有文件名
done
4.遍历文本
filename=test.txt
while read line;do
echo $line # 遍历文件的每行
done < $filename
while read line;do
echo $line# 遍历文件的每行
done <<< `cat test.txt`
#使用管道读取文件内容
sort -k 2 -nr num.txt | while read num1 num2 num3;do
echo $((num1+num2+num3));
done
八、正则表达式
九、攻略
- 终端打印、算术运算、常用变量
- 从键盘或文件中获取标准输入:read命令
- 文件的描述符和重定向
- 数组、关联数组和别名的使用
- 函数的定义、执行、传参和递归函数
- 条件测试操作与流程控制语句
- 获取时间日期格式和延时:date命令、sleep命令
- 内部字段分隔符IFS和脚本的调试DEBUG
- 显示、读取或拼接文件内容:cat命令
- 文件查找与打印文件列表:find命令
- 命令传参过滤器、命令组合工具:xargs命令
- 字符转换、删除及压缩工具:tr命令
- 对文本进行排序、单一和重复操作:sort命令、uniq命令
- 切分文件名提取文件扩展名或提取文件名:%、%% 和 #、##
- Shell的正则表达式
- 在文件中搜索文本工具:grep命令
- 按列切分文件字段工具:cut命令
- 文本处理流编辑器:sed命令
- 对文本和数据进行处理:awk编程
- 临时文件的命名方法与随机数:tempfile命令
- 创建任意大小的文件和分割任意大小的文件:dd命令、split命令、csplit命令
- Linux文件比较,文本文件的交集、差集与求差:comm命令
- 使用命令下载网站文件或网页:wget命令、lynx命令
- 命令行下的高级网络工具:curl命令
- 监视文件及目录访问信息并记录:inotifywait命令
- Linux系统日志的相关命令、文件和管理工具:logrotate命令、logger命令
- 当前登录用户、启动日志及启动故障相关信息:who命令、w命令、users命令、uptime命令、last命令、lastb命令
- 计算命令执行花费的时间信息:time命令
- 数据归档和解压缩:tar命令、cpio命令、gzip命令、bzip2命令、zip命令