Linux学习——Shell语法

拖了很多终于开始学系列-Shell语法

编写Hello world

1
2
3
4
5
6
7
[root@VM_234_23_centos ~]# vim hello.sh
---hello.sh
echo "Hello world!"

----
[root@VM_234_23_centos ~]#sh hello.sh
Hello world!

执行方式

有两种执行方式

  • sh : 例如上面的 # sh hello.sh
    实际上使用的是/bin/bash程序,它会在一个新的bash环境内执行脚本内的指令!可以理解为在当前进程新建一个子程序bash进行程序的处理。(跟多线程相似,bash是子线程,私有变量不影响主进程的变量)。
  • source : 在本bash程序中执行,所有操作在原本的bash中生效。(大概可以理解为,是在原来的进程中操作,变量定义和修改都会影响到原来的bash)。

判断式

test指令

这个指令可以用来检测某些文件或者相关的属性,更多使用在命令行中输入man test之后,能看到相关参数的说明。

1
2
3
4
5
6
7
8
9
# 测试文件是否存在,单纯的test是不会返回执行结果的
[root@VM_234_23_centos ~]# test -e index.html
# 我们可以根据上一次的执行结果来判断指令是否成功
[root@VM_234_23_centos ~]# echo $?
0
# 关于 &&(与) || (或)的操作
# PS shell里面好像没有指令的优先级这一说法,所以在处理逻辑运算时,要记得带小括号或者编写的顺序
[root@VM_234_23_centos ~]# test -e index.html && echo "file exist" || echo "Not exist"
file exist

Shell script的默认函数($0,$1…)

实际写一个指令,大概就能明白默认函数的位置了

1
2
/path/to/scirptname parm1 parm2 parm3 parm4
$0 $1 $2 $3 $4

  • $0 : 脚本档名
  • $1 : 第一个参数
  • $2 : 第二个参数
  • $# : 参数的个数
  • $@ : 表示参数列表,例如上面的,表示[ “$1”, “$2”, “$3”, “$4”],每个变量是独立的。
  • $* : 表示[ “$1c$2c$3c$4” ],其中c为分割字符,默认是空格键

shift:造成参数变量号码偏移

感觉偏移就像是移动参数数组的下标

先编写一个程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@VM_234_23_centos ~]vim shift_test.sh
echo "This program script name is : $0"
echo "Before Shift"
echo "This program paramters number is : $#"
echo "Your whole paramter is : $@"
echo "The first number is : $1"
echo "After Shift"
shift 3
echo "Your whole paramters number is : $#"
echo "Your whole paramter is : $@"
echo "The first number is : $1"
echo "End"

最后进行保存和退出:wq

来看执行结果

1
2
3
4
5
6
7
8
9
10
11
12
[root@VM_234_23_centos ~]
sh shift_test.sh parm1 parm2 parm3 parm4 parm5 parm6
This program script name is : shift_test.sh #档名
Before Shift
This program paramters number is : 6 #参数数量
Your whole paramter is : parm1 parm2 parm3 parm4 parm5 parm6 #全部变量
The first number is : parm1
After Shift # 移动之后
Your whole paramters number is : 3 # 参数下标移动了,总数量也就相应变少了
Your whole paramter is : parm4 parm5 parm6
The first number is : parm4
End


条件判断式

利用 if…then

if条件成立的话,执行then之后的语句,格式如下:

1
2
3
if [条件判断式] ; the
xxxx # 条件成立时,可以进行的指令工作内容
fi # 反过来表示if语句段结束的意思

条件判断式中,当有多个条件要判别时,常用以下两个:

  • && 代表 AND
  • || 代表 OR

多重判断式

两种情形:成功或者失败

1
2
3
4
5
6
# 一个条件的判断,分为成功和失败的执行(else)
if [条件判断式 ]; then
成功语句
else
条件失败时执行的语句
fi

多个条件

1
2
3
4
5
6
7
if [条件一] ; then
条件一成功时执行的语句
elif [条件二] ; then
条件二成功时执行的语句
else
以上条件都不成立时,执行这一条语句
fi


case…esac

以case开始,esac结束。具体语法如下

1
2
3
4
5
6
7
8
9
10
11
12
case ${变量名称} in
"第一个变量内容") #每个变量内容建议使用双引号括起来,关键词为小括号 )
程序段
;; # 每个类别结尾使用两个连续的分号来处理
"第二个变量内容")
程序段
;;
*) # 最后一个变量内容都会用 * 来代表所有其他值(有点像default节点hhh)
上面语句都没有执行的话,这段内容会被执行
exit 1
;;
esac # case的结尾,【反过来写】


function功能

【函数(function)】,类似于一个定义执行指令的片段封装体,例如:

1
2
3
function fname() {
程序段
}

注意点:shell script的执行方式是由上而下,由左而右,因此在shell script当中的function的设定一定要在程序的最前面。

例如下面例子,定义一个简单的打印函数,然后通过输入的参数进行case选择进行打印:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[root@VM_234_23_centos ~]vim test.sh
function printit() {
echo "Your choice is "
}

echo "This program will print yout selection !"
case ${1} in
"one")
printit; echo ${1} | tr 'a-z' 'A-Z' # 转换大小写
;;
"two")
printit; echo ${1} | tr 'a-z' 'A-Z'
;;
*)
echo "The param not match"
;;
esac

保存之后,执行代码:

1
2
3
4
[root@VM_234_23_centos ~]sh test.sh one
This program will print yout selection !
Your choice is
ONE

书本中也提到,一行代码的函数看起来的确有点鸡肋,但是可以封装多条指令,变成一个模块,抽象重复的代码,提高代码整洁度。

function也有内建变量,与shell script很类似,函数名称$0,后续变量是 $1,$2… ,但只在函数内生效噢~


循环Loop

循环可以不断的执行某个程序段落,知道用户设定的条件达成为止。

while do done,until do done(不定循环)

①:当condition条件成立时,就进行循环,直到condition的条件不成立才停止

1
2
3
4
while [condition] # 中括号内的状态就是判断式
do # 标志着循环的开始
程序段
done # 标志着循环的结束

②:until

1
2
3
4
until [condition]
do
程序段
done

这两者之间其实是很类似的,区别在于,while循环时,至少会判断一次condition,而until运行到循环语句时,直接执行程序段,然后在第二次循环前再判断condition。

for…do…done(固定循环)

这种循环是知道要进行多少次循环,通常循环体是一个数组,对每一个参数进行遍历处理。

①:foreach形式

1
2
3
4
for var in con1 con2 con3 ...
do
程序段
done

②:自定义步长的处理

1
2
3
4
5
6
7
8
9
10
for ((初始值; 限定值; 执行步长 ))
do
程序段
done

例如:
for (( i = 1; i < ${number}; i = i + 1 ))
do
程序段
done


了解一下数组的写法

跟平常的数组一样,通过下标来指定数组中每个值,同样下标也是从0开始的哟~

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[root@VM_234_23_centos ~]vim list.sh
function print_list() {
local numbers # 声明本地变量
numbers=(`echo "$@"`) # 将传参转回数组,不这样做的话,$1会被当成是一个整体字符哟
size=${#numbers[*]}
for (( i=0; i<${size}; i=i+1 ))
do
echo "The ${i} number is ${numbers[i]}"
done
}
list=(0 1 2 3 4)
print_list "${list[*]}" # 传递一个数组到方法中
[root@VM_234_23_centos ~]sh list.sh
The 0 number is 0
The 1 number is 1
The 2 number is 2
The 3 number is 3
The 4 number is 4

上面的例子大概写了如何定义一个函数、将数组作为传参、在函数内将传参数组转化还有数组的for循环~


参考资料

1、《鸟哥的Linux私房菜-基础篇》