Hello world
shell脚本和一般程序并没有太多的差别,脚本文件基本形态,以#开头表示注释,直到行末,先来个Hello world吧
#!/bin/sh # 声明shell脚本解释器,没有声明则使用默认的shell解释器,不同的shell解释器语法有一定的区别,所以都要加上此句
a = "hello world" # 变量不需要定义,无数据类型
echo $a # 输出 hello world
echo "output ${a}abc" # 输出 output hello worldabc (如果变量后面还有字符则用{}括起来,$表示取变量的值)
保存为test文件,使用命令行执行./test,输出为output hello worldabc
系统变量

条件表达式

语法规则
if语句
if [表达式] # 表达试多个组合情况下和C一样,前面已经成立的后面就不再执行
then
[语句组]
elif [表达式] # else if
then
[语句组]
else
[语句组]
fi
for语句
for 变量 in 值的范围(可用通配符,命令的输出等)
do
[语句组]
done
例:
a=2
for a in 1 2 3 "ab"c # 循环体执行4次
do
echo $a
done
输出为:123abc
while语句
while [表达式]
do
[语句组]
done
until语句
until [表达式] # 表达式为真时退出循环
do
[语句组]
done
case语句
case 变量 in
情况1[|情况2...]) 语句组 ;; # ;;表示break
情况3[|情况4...]) 语句组 ;;
...
*) 语句组 ;; # 相当于default
esac
例:
#!/bin/sh
read a # 等待输入
case "$a" in
y|yes) echo "yes" ;;
n|no) echo "no" ;;
*) echo "default"
esac
函数
定义:函数名() (没有返回值类型、参数,写在调用前面)
#!/bin/sh
fun(){
echo $1
echo $2
return 0
}
echo "call fun"
a = fun aa bb
echo $a
理论输出(获取返回值可能出错):call fun aa bb 0
获取返回值后函数中的echo可能不会显示,全被捕获到返回值中(待验证) 函数中声明局部变量在变量前加local
fun(){
local a
a = 10
...
}
break命令
用于跳出循环(for while until),可以带一个参数,表示跳出循环的层数
for [表达式]
do
[语句组]
if [表达式]
then
beeak; # ;可有可无
fi
done
:命令
空操作,相当于true或汇编中的nop(),但效率高,用于while : (也就是我们C中常用的while(true))
continue命令
用法和C相同(结束本次循环继续下一个)
.命令
代表当前目录,例如执行当前目录下的test文件 ./test
eval命令
将表达式得到的结果以shell的形式再执行一次
#!/bin/sh
foo = 10
x = foo
y = '$'$x
echo $y
输出:$foo
#!/bin/sh
foo = 10
x = foo
eval y = '$'$x # 等效于y = $(($x)) (应该是y = eval '$'$x吧,待验证)
echo $y
输出:10
exec命令
执行另一个shell程序,执行完不会再返回,exec命令后面的语句不会被执行
#!/bin/sh
exec echo "execute"
echo "next" # 不会被执行
exit命令
退出程序,可带一个参数,0表示正常退出
export命令
导出,相当于C中.h文件的变量声明,给不同的文件使用 export1文件
#!/bin/sh
foo = "aaa"
export foo
./export2
export2文件
#!/bin/sh
echo "$foo"
输出:aaa
set命令
设置参数到s1、s2、s3...
#!/bin/sh
echo $(data) # data获取系统时间
set $(data)
echo $2 # $2中保存着月份
unset命令
删除变量
#!/bin/sh
foo = "aaa"
unset foo
echo $foo # 输出为空
declare命令
Linux declare命令用于声明 shell 变量。
shell定义字典
declare -A dic
dic=([key1]="value1" [key2]="value2" [key3]="value3")
打印指定key的value
echo ${dic["key1"]}
打印所有key值
echo ${!dic[*]}
打印所有value
echo ${dic[*]}
字典添加一个新元素
dic+=([key4]="value4")
遍历key值
for key in $(echo ${!dic[*]})
do
echo "$key : ${dic[$key]}"
done
shell定义数组
list=("value1" "value2" "value3")
打印指定下标
echo ${list[1]}
打印所有下标
echo ${!list[*]}
打印数组下标
echo ${list[*]}
数组增加一个元素
list=("${list[@]}" "value3")
按序号遍历
for i in "${!arr[@]}"; do
printf "%s\t%s\n" "$i" "${arr[$i]}"
done
按数据遍历
for NUM in ${ARR[*]}
do
echo $NUM
done
按照某一格式切割保存到数组
按照逗号切割字符串,将逗号转为空格,因为shell定界符默认是空格
array=${var//,/ }
其中IFS保存的是shell定界符
OLD_IFS="$IFS"
IFS=","
array=($var)
IFS="$OLD_IFS"
遍历数组
for element in ${arr[@]}
do
...
done
if[X$1 = X];then
是用来测试命令列上有没有参数。
$1 可以换成指定变量,判断变量是否有值。
if[$? -ne 0];then
$?是最近执行的命令的退出状态;
按惯例,0表示成功,其他任何表示失败。
此语句检测最近执行的命令返回状态是否成功。
rm
删除文件或目录
-r, -R, --recursive
以递归方式删除目录及其内容
-f, --force
忽略不存在的文件,永远不会提示
/
删除(取消链接)文件。
打印或设置系统日期和时间
`date +%s`
expr
评估表达式
sed
用于过滤和转换文本的流编辑器
-i[SUFFIX], --in-place[=SUFFIX]
在指定位置编辑文件(如果提供扩展,则进行备份)
-e, --expression, -f, or --file
在指定文件插入指定表达式
-n, --quiet, --silent
suppress automatic printing of pattern space
检测三种不同的操作系统类型(GNU / Linux,Mac OS X,Windows NT)
在你的bash脚本中,使用#!/ usr / bin / env bash而不是#!/ bin / sh来防止/ bin / sh导致的问题链接到不同平台的不同默认shell,否则会出现意外运算符等错误。
Mac OS X 10.6.8(Snow Leopard)没有expr程序,除非你安装了,所以我只使用uname。
#!/usr/bin/env bash
if [ "$(uname)" == "Darwin" ]; then
# Do something under Mac OS X platform
elif [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]; then
# Do something under GNU/Linux platform
elif [ "$(expr substr $(uname -s) 1 10)" == "MINGW32_NT" ]; then
# Do something under 32 bits Windows NT platform
elif [ "$(expr substr $(uname -s) 1 10)" == "MINGW64_NT" ]; then
# Do something under 64 bits Windows NT platform
fi
cp -R
复制文件和目录
-R, -r, --recursive
递归复制目录