helloworld

1
2
#!/bin/bash
echo "Hello World !"

运行
chmod +x ./test.sh #使脚本具有执行权限 ./test.sh #执行脚本

使用string

1
2
3
4
5
6
7
#!/bin/bash
str='this is a string'
echo ${str}
echo ${#str} # 获取字符传长度
echo `expr index ${str} io` # 查找字符 i 或 o 的位置(哪个字母先出现就计算哪个)


推荐给所有变量加上花括号,这是个好的编程习惯。
推荐使用双引号 ,单引号则没有这些功能(#{})

  • 双引号里可以有变量
  • 双引号里可以出现转义字符

使用数组

1
2
3
4
5
6
#!/bin/bash
array_name=(a b c d)
echo ${array_name[2]}
echo ${array_name[@]} # 获取数组中的所有元素
echo ${#array_name[@]} # 获取数组长度

注释

1
2
3
4
5
# 单行注释
:<<EOF
多行注释
多行注释
EOF

启动脚本并且传参

1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/bash
echo "执行的文件名:$0"
echo "执行的参数1:$1"
echo "执行的参数2:$2"
echo "执行的参数3:$3"
echo "脚本参数个数:$#"
echo "脚本所有参数:$*"
echo "脚本进程号:$$"
echo "脚本所有参数 "$@"" #不同点:只有在双引号中体现出来。假设在脚本运行时写了三个参数 1、2、3,,则 " * " 等价于 "1 2 3"(传递了一个参数),而 "@" 等价于 "1" "2" "3"(传递了三个参数)。
echo "shell当前选项:$-"
echo "shell退出状态:$?"

“$@”于$*不同点:只有在双引号中体现出来。假设在脚本运行时写了三个参数 1、2、3,,则 “ * “ 等价于 “1 2 3”(传递了一个参数),而 “@” 等价于 “1” “2” “3”(传递了三个参数)。

关联数组

1
2
3
4
5
6
7
8
9
#!/bin/bash
declare -A site
site["google"]="www.google.com"
site["runoob"]="www.runoob.com"
site["taobao"]="www.taobao.com"

echo ${site["runoob"]} # www.runoob.com
echo "数组的键为: ${!site[*]}" # google runoob taobao
echo "数组元素个数为: ${#my_array[*]}" # 数组元素个数为: 4
基本运算符

bash不支持原生简单数据运算,但是支持使用expr 和awk命令

  • 表达式和运算符之间要有空格,例如 2+2 是不对的,必须写成 2 + 2,这与我们熟悉的大多数编程语言不一样。
  • 完整的表达式要被 包含,注意这个字符不是常用的单引号,在 Esc 键下边。
    1
    2
    3
    #!/bin/bash
    sum = `expr 1 + 1`
    echo ${sum}
基本运算 + - * / % = == !=

注意:条件表达式要放在方括号之间,并且要有空格,例如: [$a==$b] 是错误的,必须写成 **[ $a == $b ]**。
a=$b 把变量 b 的值赋给 a。
[ $a == $b ] 返回 false。

关系运算符

-eq -ne -gt (大于) -ge(大于等于) -lt -le

布尔运算符

非! 或-0 与-a
[ $a -lt 100 -a $b -gt 15 ]

逻辑运算符

&& ||

文件测试运算符
-d file 检测文件是否是目录,如果是,则返回 true。
-f file 检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。
-r file 检测文件是否可读,如果是,则返回 true。
-w file 检测文件是否可写,如果是,则返回 true。
-x file 检测文件是否可执行,如果是,则返回 true。
-s file 检测文件是否为空(文件大小是否大于0),不为空返回 true。
-e file 检测文件(包括目录)是否存在,如果是,则返回 true。

shell echo命令

1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/bash
echo "helloWorld" # helloWorld
echo helloWorld # helloWorld
echo \"helloWorld\" #helloWorld
read name
echo "$name It is a test"
echo -e "OK! \c" # -e 开启转义 \c 不换行
echo "It is a test"
echo '$name\"' # 原样输出字符串,不进行转义或取变量(用单引号)
echo "It is a test" > myfile # 显示结果生成到文件
echo `date` # 显示命令执行结果 命令用反引号`

shell printf命令

printf 使用引用文本或空格分隔的参数,外面可以在 printf 中使用格式化字符串,还可以制定字符串的宽度、左右对齐方式等。默认的 printf 不会像 echo 自动添加换行符,我们可以手动添加 \n
%s %c %d %f 都是格式替代符,%s 输出一个字符串,%d 整型输出,%c 输出一个字符,%f 输出实数,以小数形式输出。
%-10s 指一个宽度为 10 个字符(**-** 表示左对齐,没有则表示右对齐),任何字符都会被显示在 10 个字符宽的字符内,如果不足则自动以空格填充,超过也会将内容全部显示出来。
%-4.2f 指格式化为小数,其中 .2 指保留2位小数。

1
2
3
#!/bin/bash
printf "%-10s %-8s %-4s\n" 姓名 性别 体重kg
printf "%-10s %-8s %-4.2f\n" 郭靖 男 66.1234
\c 抑制(不显示)输出结果中任何结尾的换行字符(只在%b格式指示符控制下的参数字符串中有效),而且,任何留在参数里的字符、任何接下来的参数以及任何留在格式字符串中的字符,都被忽略
\f 换页(formfeed)
\n 换行
\r 回车(Carriage return)
\t 水平制表符
\v 垂直制表符

字符串控制

-z 字符串 字符串的长度为零则为真
-n 字符串 字符串的长度不为零则为真

流程控制

if else
1
2
3
4
5
6
7
if condition
then
command1
command2
...
commandN
fi
if elseif else
1
2
3
4
5
6
7
8
9
if condition1
then
command1
elif condition2
then
command2
else
commandN
fi

if else 的 […] 判断语句中大于使用 -gt,小于使用 -lt
如果使用 ((…)) 作为判断语句,大于和小于可以直接使用 > 和 **<**。
Shell中的 test 命令用于检查某个条件是否成立,它可以进行数值、字符和文件三个方面的测试。

for循环
1
2
3
4
5
6
7
8
9
for var in item1 item2 ... itemN
do
command1
command2
...
commandN
done
# 写成一行
for var in item1 item2 ... itemN; do command1; command2… done;
while循环
1
2
3
4
5
6
7
8
9
while condition
do
command
done
#无限循环
while :
do
command
done
untill循环
1
2
3
4
until condition
do
command
done

until 循环执行一系列命令直至条件为 true 时停止。
until 循环与 while 循环在处理方式上刚好相反。
一般 while 循环优于 until 循环,但在某些时候—也只是极少数情况下,until 循环更加有用。

case … esac多选择语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
echo '输入 1 到 4 之间的数字:'
echo '你输入的数字为:'
read aNum
case $aNum in
1) echo '你选择了 1'
;;
2) echo '你选择了 2'
;;
3) echo '你选择了 3'
;;
4) echo '你选择了 4'
;;
*) echo '你没有输入 1 到 4 之间的数字'
;;
esac
跳出循环
1
2
break # 跳出所有循环
continue # 跳出当前循环

shell 函数

所有函数在使用前必须定义。这意味着必须将函数放在脚本开始部分,直至shell解释器首次发现它时,才可以使用。调用函数仅使用其函数名即可。
参数返回,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值。 return后跟数值n(0-255
传参如同启动脚本并且传参的格式
$10 不能获取第十个参数,获取第十个参数需要${10}。当n>=10时,需要使用${n}来获取参数。
函数与命令的执行结果可以作为条件语句使用。要注意的是,和 C 语言不同,shell 语言中 0 代表 true,0 以外的值代表 false。
$? 仅对其上一条指令负责,一旦函数返回后其返回值没有立即保存入参数,那么其返回值将不再能通过 $? 获得。

1
2
3
4
5
6
7
8
9
[ function ] funname [()]

{

action;

[return int;]

}

实例(有返回值)

1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/bash
funWithReturn(){
echo "这个函数会对输入的两个数字进行相加运算..."
echo "输入第一个数字: "
read aNum
echo "输入第二个数字: "
read anotherNum
echo "两个数字分别为 $aNum 和 $anotherNum !"
return $(($aNum+$anotherNum))
}
funWithReturn
echo "输入的两个数字之和为 $? !"

输入输出重定向

命令 说明
command > file 将输出重定向到 file。
command < file 将输入重定向到 file。
command >> file 将输出以追加的方式重定向到 file。
n > file 将文件描述符为 n 的文件重定向到 file。
n >> file 将文件描述符为 n 的文件以追加的方式重定向到 file。
n >& m 将输出文件 m 和 n 合并。
n <& m 将输入文件 m 和 n 合并。
<< tag 将开始标记 tag 和结束标记 tag 之间的内容作为输入。

接着以上实例,我们需要统计 users 文件的行数,执行以下命令:
$ wc -l users 2 users
也可以将输入重定向到 users 文件:
$ wc -l < users 2
注意:上面两个例子的结果不同:第一个例子,会输出文件名;第二个不会,因为它仅仅知道从标准输入读取内容。

Here Document

Here Document 是 Shell 中的一种特殊的重定向方式,用来将输入重定向到一个交互式 Shell 脚本或程序。

1
2
3
command << delimiter
document
delimiter
/dev/null 文件

如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null:
$ command > /dev/null

一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件:

  • 标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。
  • 标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。
  • 标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。

如果希望 stderr 重定向到 file,可以这样写:
$ command 2>file

shell 文件包含

. filename # 注意点号(.)和文件名中间有一空格 或 source filename
用以调用被包含的参数
被包含的文件 test1.sh 不需要可执行权限。