Linux shell 学习笔记(16)— shell 入门总结

1. Shell 变量

Shell 变量包括自定义变量和环境变量:

  • 自定义变量:脚本中自己命名定义的变量,通常为局部变量,其他 Shell 程序不能访问到;
  • 环境变量,操作系统已定义的变量,如 PATH,所有 Shell 程序都能访问到,也可以通过 env 查看所有环境变量。
wohu@ubuntu-dev:~$ env | grep -i shell
SHELL=/bin/bash		# 当前用户 Shell 类型
wohu@ubuntu-dev:~$ env | grep HOME
HOME=/home/wohu	# 当前用户主目录
wohu@ubuntu-dev:~$ env | grep LANG
LANG=en_US.UTF-8	# 操作系统字符集
GDM_LANG=en_US
LANGUAGE=en_US
wohu@ubuntu-dev:~$
变量名 说明
$PWD 脚本执行的当前所在目录
$UID 当前操作的系统用户 ID
$$ 当前操作用户的 PID
$# 当前脚本的参数个数
$* 当前脚本的所有参数
$0 当前执行程序的名称
$n 当前程序的第 N 个参数
$HOME 当前程序的 home 目录
$USER 查询当前程序使用的操作用户

1.1 命名

变量名由字母、数字、下划线组成,只能以字母或者下划线开头,不能使用 Shell 的保留字。不能使用空格、不能使用标点符号。

1.2 赋值、调用

  1. 新建 hello.sh 脚本,扩展名不影响执行:
#!/bin/bash
#自定义变量 hello
hello="Hello world!"; //注意等号两边不能有空格
echo $hello;
  1. hello.sh 脚本赋予执行权限:chmod +x hello.sh

  2. 调用脚本 ./hello.shhello.sh 的前面需要加上 ./,这是因为不加上的话会去 PATH 下查找是否有对应的命令可以执行,而 PATH 下只有 /bin/sbin/usr/bin/usr/sbin,通常当前目录不在 PATH 下,就会提示 comman not found,所以要用 ./ 告诉系统在当前目录下查找。

# 变量名=值
如:A=1   等号两边不要有空格,如果值中间存在空格,请使用单引或者双引号:A='张 三'

# 撤销变量
unset A

# 定义静态变量,静态变量不可以二次赋值,静态变量不可以 unset 撤销
readonly B=2

1.3 删除

使用 unset 命令可以删除变量:

unset variable_name

例如:

#!/bin/bash
hello="Hello world!"
echo "hello="$hello
unset hello
echo "hello="$hello

输出结果:

[oracle@195 ~]$ ./hello.sh 
hello=Hello world!
hello=

1.4 作用域

普通的变量作用域为当前的执行程序,程序外部不可使用当前定义的变量。通过 export 可以把变量升级为全局环境变量,这样当前系统所有程序都可以使用这个环境变量。

export name="wohu"

测试文件,会输出 “wohu”

#!/bin/bash
echo $name

由于定义了全局变量,所以执行脚本可以正常输出 $name 变量的值,反之脚本中定义的局部变量,在其它脚本中不能引用。

2. Shell 字符串

2.1 单引号、双引号

Shell 中最常用的数据类型就是字符串和数字,除此之外也没有数据类型了,在 Shell 中字符串可以用单引号或者双引号来包围,如: '/home/ubuntu'"/home/ubuntu"/home/ubuntu也可以没有引号包围。

两者的区别在于:

  • 单引号包围的字符串会以原样输出,且单引号包围的字符串中不能出现单引号,进行转义也不行。

如:echo 'hello ${name}',会输出:hello ${name}

  • 双引号包围的字符串会将变量进行替换,且双引号包围的字符串中可以出现双引号,进行转义就行。

如:

wohu@ubuntu-dev:~$ name="wohu"
wohu@ubuntu-dev:~$ echo "hello ${name}"
hello wohu
wohu@ubuntu-dev:~$ 
  • 不被引号包围的字符串,会对变量进行解析,这点跟双引号一样,但是字符串中不能出现空格,否则空格后面的字符串会被当作命令或者其他变量解析。

综上,当有变量时最好是使用双引号包围字符串,且变量最好有 {} 包围,明确变量名,这也是最佳编程实践。

2.2 获取字符串长度

获取字符串长度的方式有两种:

  • ${#string_name}
  • expr length string_name

示例:

#!/bin/bash
hello="Hello world!"
echo "length of hello is:"${#hello}
expr length "$hello"

输出结果:

length of hello is:12
12

2.3 截取字符串

使用 # 截取右边字符,方式为 ${hello#*chars},例如:

#!/bin/bash
hello="Hello world!"
echo ${hello#*o}

输出:

world!

表明截取了从左到右第一个 o 右边的字符串,*chars 代表忽略 chars 左边任意长度的字符串(包括 chars)。如果不写星号,那么就不会忽略 chars 左边的字符串。

#!/bin/bash
hello="Hello world!"
echo ${hello#o}

输出:

Hello world!

使用 % 截取左边字符串,方式为:${hello%chars_}__。与 _#_ 不同的是,这里_在右边,代表忽略 chars 右边的任意长度字符串,来截取 chars 左边的字符串,其用法跟 # 类似。

看个例子:

#!/bin/bash
hello="Hello world!"
echo ${hello%o*}

输出:

Hello w

3. Shell 数组

Shell 数组只能是一维的,不支持多维数组,并且 Shell 是弱类型的,数组中的类型不一定只有一种,且不限制数组的长度大小,理论上可以是无限大小。

#!/bin/bash
#创建数组
array=(a b c d e)

#获取数组长度
length1=${#array[@]}
echo "length1=${length1}"

#另一种获取数组长度方法
length2=${#array[*]}
echo "length2=${length2}"

#获取第三个元素
echo ${array[2]}

#删除第二个元素
unset array[1]

#输出整个数组
echo ${array[@]}

#for 遍历整个数组
for i in ${array[@]}
do 
	echo $i
done;

#删除整个数组
unset array
#查看是否已删除
for i in ${array[@]}
do 
	echo $i
done;

输出:

length1=5
length2=5
c
a c d e
a
c
d
e

4. Shell 基本运算符

4.1 算数运算符

包括:+-*/%===!=,这些跟我们其他编程语言遇到的是一样的,举个简单例子。

#!/bin/bash
a=1;
b=2;
c=`expr $a + $b`;
echo "total is: ${c}";

if [ $a == $b ]
then
echo "a 等于 b"
fi

if [ $a != $b ]
then
echo "a 不等于 b"
fi

输出:

total is: 3

4.2 关系运算符

运算符 说明
-eq 判断两个数据是否相等
-nq 判断两个数据是否不相等
-gt 判断左边的数据是否大于右边的数据
-lt 判断左边的数据是否小于右边的数据
-ge 判断左边的数据是否大于等于右边的数据
-le 判断左边的数据是否小于等于右边的数据
#!/bin/bash
a=100;
b=99;
if [ $a -eq $b ]
then
  echo "A"
else
  echo "B"
fi

输出:B

4.3 逻辑运算符

运算符 说明
&& 逻辑与,左右两边的表达式都为 true 才 true,有一个为 false 则为 false

接下来看下程序

#!/bin/bash
a=100;
b=99;
c=90;
if [[ $a -gt $b && $a -gt $c ]]
then
  echo "A"
elif [[ $b -gt $a && $b -gt $c ]]
then
  echo "B"
else
  echo "C"
fi

输出:A

4.4 布尔运算符

运算符 说明
非运算,对表达式取反,如:[ !false ] 返回 false
-o 或运算,左右两边的表达式存在 true 则为 true,都为 false 则为 false
-a 与运算,左右两边的表达式存在 false 则为 false,都为 true 则为 true

接下来看下程序

#!/bin/bash

a=100;
b=99;
c=90;
if !((a == b))
then
  echo "a 与 b 不相等"
else
  echo "a 与 b 相等"
fi

if [ $a -gt $b -a $a -gt $c ]
then
  echo "A"
elif [ $b -gt $a -a $b -gt $c ]
then
  echo "B"
else
  echo "C"
fi

输出:
a 与 b 不相等
A

-a-o 用法相同。

4.5 字符串运算符

运算符 说明
= 检测两个字符串是否相等,相等返回 true
!= 检测两个字符串是否不相等,不相等则返回 true
-z 检测字符串长度是否为 0,为 0 则返回 true
-n 检测字符串长度是否为 0,不为 0 则返回 true
$ 检测字符串是否为空,不为空则返回 true
#!/bin/bash
a="zoom"
b=""
if [ -n $a ]
then
  echo "a 长度不为 0"
else
  echo "a 长度为 0"
fi

if [ -z $b ]
then
  echo "b 长度为 0"
else
  echo "b 长度不为 0"
fi

if [ $b ]
then
  echo "b 不为空字符串"
else
  echo "b 是空字符串"
fi

输出:

a 长度不为 0
b 长度为 0
b 是空字符串

5. Shell 流程控制

5.1 if 条件语句

#!/bin/bash
if conditionA
then
		exprA
elif conditionB
then
		exprB
else
		exprC
fi

这就是 if-elif-else,最后别忘了 fi 作为结尾。Shellif 不能有空语句,即什么都不做的条件表达式。还有一点是 condition 一般用中括号 []Java都是用小括号 ()

5.2 for 循环语句

for 循环语句的基本语法是:

#!/bin/bash
for loop in item1 item2 ... itemN
do
  condition1
  condition2
  ...
  conditionP
done

其中,for loop in 1 2 3 4 5 可被替换成 for loop in {1..5}。以及 类似于 C 中的 for 条件语句写法:for((i=0;i<=5;i++))

#!/bin/bash
for((i=0;i<=5;i++))
do
	echo "num is ${i}"
done

输出:

num is 0
num is 1
num is 2
num is 3
num is 4
num is 5

5.3 while 循环语句

基本语法是:

#!/bin/bash
while conditionA
do
  commandA
done

看个例子:

#!/bin/bash
i=0
while(( i<=5 ))
do
	echo "num is ${i}"
	let i++
done

while 语句还可以用来接收用户输入,用法是:

while read choose

无限循环是经常会用到的一个语法,下面列举了无限循环的三种实现方式:

  • while :
  • while true
  • for(( ; ; ))

5.4 case 语句

*) 表示默认模式,相当于 default;; 表示命令序列结束,相当于 break

!/bin/bash

case $1 in
"1")
echo "张三"
;;

"2")
echo "李四"
;;
*)
echo "王二"
;;
esac

6. Shell 函数

6.1 系统函数

6.1.1 basename

basename 路径 后缀

功能描述:basename 命令会删掉所有的前缀包括最后一个 /字符,然后将字符串显示出来。

  1. 不加后缀
wohu@ubuntu-dev:~/git_demo$ basename /home/wohu/git_demo/
git_demo
wohu@ubuntu-dev:~/git_demo$
  1. 加后缀
wohu@ubuntu-dev:~/git_demo$ basename /home/wohu/git_demo/demo.sh  .sh
demo
wohu@ubuntu-dev:~/git_demo$

6.1.2 dirname

dirname 文件绝对路径     

功能描述:从给定的包含绝对路径的文件名中去除文件名(非目录的部分),然后返回剩下的路径(目录的部分)。

wohu@ubuntu-dev:~/git_demo$ dirname  /home/wohu/git_demo/demo.sh  
/home/wohu/git_demo
wohu@ubuntu-dev:~/git_demo$ 

6.2 自定义函数

#!/bin/bash
printnum()
{
    echo "my first function"
}

echo "call funtion start"
printnum
echo "call funtion end"

输出:

call funtion start
my first function
call funtion end

这个是不带参数没有返回值的例子,接下来我们来看看不带参数没有返回值的例子:

#!/bin/bash
plusnum()
{
    a=1
    b=3
    return $((a+b))
}

plusnum
echo "a+b="$?

从上面我们可以看出,在调用函数后,通过 $?可以拿到返回结果。而调用方式是直接用函数名即可,不需要加上括号,这点跟 Java 和其他面向对象的编程语言都有所不同。

下面再看一个有参数的函数:

#!/bin/bash
plusnum()
{
    a=$1
    b=$2
    return $((a+b))
}

plusnum 99 100
echo "a+b="$?

从上面我们可以看到函数 plusnum 中通过 $1$2 获取传入的参数,在相加后返回结果,调用时直接跟在函数后面,并不像 Java 的函数传参。

注意事项:

  • 必须在调用函数地方之前,先定义函数,Shell 脚本是逐行运行。不会像其它语言一样先编译。
  • 函数返回值,只能通过 $? 系统变量获得,可以显式地加 return 返回,如果不加,将以最后一条命令运行结果,作为返回值。return 后跟数值 n(0~255)。

示例:

#!/bin/bash

function sum()
{
	s=0
	s=$[ $1 + $2 ]
	echo "$s"
}

# read 读取控制台的输入,n1, n2 用于接收输入内容,
# -p:指定读取值时的提示符; 
# -t:指定读取值时等待的时间(秒)
read -p "Please input the number1: " n1;
read -p "Please input the number2: " n2;
# 调用方法
sum $n1 $n2;

你可能感兴趣的:(Linux,linux,oracle,ubuntu)