Shell基础回顾

个人专题目录

1. Shell解析器

  1. Linux提供的Shell解析器有:
$ cat /etc/shells 
/bin/sh
/bin/bash
/sbin/nologin
/bin/dash
/bin/tcsh
/bin/csh
  1. bash和sh的关系
$ ll /bin | grep bash
-rwxr-xr-x. 1 root root 941880 5月  11 2016 bash
lrwxrwxrwx. 1 root root      4 5月  27 2017 sh -> bash
  1. Centos默认的解析器是bash
$ echo $SHELL
/bin/bash

2. Shell脚本入门

  1. 脚本格式

脚本以#!/bin/bash开头(指定解析器)这一行决定了脚本可以像一个独立的可执行文件一样执行,而不用在终端之前输入sh,bash,python,php等。

  1. 第一个Shell脚本:helloworld
    1. 需求:创建一个Shell脚本,输出helloworld
    2. 案例实操:
$ touch helloworld.sh
$ vi helloworld.sh

在helloworld.sh中输入如下内容
#!/bin/bash
echo "helloworld"
  1. 脚本的常用执行方式

第一种:采用bash或sh+脚本的相对路径或绝对路径(不用赋予脚本+x权限)

# sh+脚本的相对路径
$ sh helloworld.sh

#sh+脚本的绝对路径
$ sh /home/xubh/datas/helloworld.sh 
helloworld

#bash+脚本的相对路径
$ bash helloworld.sh 
Helloworld

#bash+脚本的绝对路径
$ bash /home/xubh/datas/helloworld.sh 
Helloworld

第二种:采用输入脚本的绝对路径或相对路径执行脚本(必须具有可执行权限+x)

# 首先要赋予helloworld.sh 脚本的+x权限
$ chmod 777 helloworld.sh

# 执行脚本
# 相对路径
$ ./helloworld.sh 
Helloworld
# 绝对路径
$ /home/xubh/datas/helloworld.sh 
Helloworld

注意:第一种执行方法,本质是bash解析器帮你执行脚本,所以脚本本身不需要执行权限。第二种执行方法,本质是脚本需要自己执行,所以需要执行权限。

  1. 第二个Shell脚本:多命令处理
# 在/home/xubh/目录下创建一个banzhang.txt,在banzhang.txt文件中增加“I love cls”。
$ touch batch.sh
$ vi batch.sh

在batch.sh中输入如下内容
#!/bin/bash

cd /home/xubh
touch cls.txt
echo "I love cls" >>cls.txt

3. Shell中的变量

系统变量

  1. 常用系统变量

HOME、PWD、SHELL、USER等

  1. 案例实操
# 查看系统变量的值
$ echo $HOME
/home/xubh

# 显示当前Shell中所有变量:set
$ set
BASH=/bin/bash
BASH_ALIASES=()
BASH_ARGC=()
BASH_ARGV=()

自定义变量

  1. 基本语法

    • 定义变量:变量=值
    • 撤销变量:unset 变量
    • 声明静态变量:readonly变量,注意:不能unset
  2. 变量定义规则

    • 变量名称可以由字母、数字和下划线组成,但是不能以数字开头,环境变量名建议大写
    • 等号两侧不能有空格
    • 在bash中,变量默认类型都是字符串类型,无法直接进行数值运算。
    • 变量的值如果有空格,需要使用双引号或单引号括起来。
  3. 案例实操

# (1)定义变量A
$ A=5
$ echo $A
5
#(2)给变量A重新赋值
$ A=8
$ echo $A
8
#(3)撤销变量A
$ unset A
$ echo $A
#(4)声明静态的变量B=2,不能unset
$ readonly B=2
$ echo $B
2
$ B=9
-bash: B: readonly variable
#(5)在bash中,变量默认类型都是字符串类型,无法直接进行数值运算
$ C=1+2
$ echo $C
1+2
#(6)变量的值如果有空格,需要使用双引号或单引号括起来
$ D=I love banzhang
-bash: world: command not found
$ D="I love banzhang"
$ echo $A
I love banzhang
#(7)可把变量提升为全局环境变量,可供其他Shell程序使用
$ vim helloworld.sh 

在helloworld.sh文件中增加echo $B
#!/bin/bash

echo "helloworld"
echo $B

$ ./helloworld.sh 
Helloworld
# 发现并没有打印输出变量B的值。
$ export B
$ ./helloworld.sh 
helloworld
2

Array

像其它语言一样,bash 也有数组类型。bash 中的数组是一个保存着很多值的变量,数组的长度没有限制,下标也是从 0 开始。在 bash 中有好几种方法创建一个数组,如下所示。

Examples:

array[0] = val
array[1] = val
array[2] = val
array=([2]=val [0]=val [1]=val)
array=(val val val)

使用如下语法获得数组特定位置的值:

${array[i]}     # i是数组下标

如果没有指定数组下标,默认返回第一个元素。想知道数组中有多少个元素,使用下面的语法:

${#array[@]}

Bash 也支持三元运算符,如下面的例子所示:

${varname:-word}    # 如果 varname 存在而且不为 null,返回它的值,否则返回 word
${varname:=word}    # 如果 varname 存在而且不为 null,返回它的值,否则把word赋值给它并且返回 word
${varname:+word}    # 如果 varname 存在而且不为 null,返回 word,否则返回 null
${varname:offset:length}    # 它返回 $varname 的子字符串,从 offset 处开始,长度为 length

String Substitution

${variable#pattern}         # 如果 pattern 匹配变量值的起始部分,删除匹配 pattern 的最短的部分,然后返回剩余的
${variable##pattern}        # 如果 pattern 匹配变量值的起始部分,删除匹配 pattern 的最长的部分,然后返回剩余的
${variable%pattern}         # 如果 pattern 匹配变量值的结束部分,删除匹配 pattern 的最短的部分,然后返回剩余的
${variable%%pattern}        # 如果 pattern 匹配变量值的结束部分,删除匹配 pattern 的最长的部分,然后返回剩余的
${variable/pattern/string}  # 把变量值中匹配 pattern 的最长的部分替换为 string,只替换第一个匹配的部分
${variable//pattern/string} # 把变量值中匹配 pattern 的最长的部分替换为 string,全局进行替换
${#varname}     # 返回变量值作为一个字符串的长度

特殊变量:$n

  1. 基本语法

n (功能描述:n为数字,0代表该脚本名称,1-9代表第一到第九个参数,十以上的参数,十以上的参数需要用大括号包含,如${10})

  1. 案例实操

    • 输出该脚本文件名称、输入参数1和输入参数2 的值
$ touch parameter.sh 
$ vim parameter.sh

#!/bin/bash
echo "$0  $1   $2"

$ chmod 777 parameter.sh
$ ./parameter.sh cls  xz
./parameter.sh  cls   xz

特殊变量:$#

  1. 基本语法

​ $#(功能描述:获取所有输入参数个数,常用于循环)。

  1. 案例实操

    • 获取输入参数的个数
$ vim parameter.sh

#!/bin/bash
echo "$0  $1   $2"
echo $#

$ chmod 777 parameter.sh

$ ./parameter.sh cls  xz
parameter.sh cls xz 
2

特殊变量:*、@

  1. 基本语法

* (功能描述:这个变量代表命令行中所有的参数,*把所有的参数看成一个整体)

@ (功能描述:这个变量也代表命令行中所有的参数,不过@把每个参数区分对待)

  1. 案例实操

    • 打印输入的所有参数
$ vim parameter.sh

#!/bin/bash
echo "$0  $1   $2"
echo $#
echo $*
echo $@

$ bash parameter.sh 1 2 3
parameter.sh  1   2
3
1 2 3
1 2 3

特殊变量:$?

  1. 基本语法

$? (功能描述:最后一次执行的命令的返回状态。如果这个变量的值为0,证明上一个命令正确执行;如果这个变量的值为非0(具体是哪个数,由命令自己来决定),则证明上一个命令执行不正确了。)

  1. 案例实操

    • 判断helloworld.sh脚本是否正确执行
$ ./helloworld.sh 
hello world
$ echo $?
0

4. 运算符

  1. 基本语法

    • ((运算式))”或“[运算式]”
    • expr + , - , *, /, % 加,减,乘,除,取余
  • 注意:expr运算符间要有空格
  1. 案例实操:
#(1)计算3+2的值
$ expr 2 + 3
5
#(2)计算3-2的值
$ expr 3 - 2 
1
#(3)计算(2+3)X4的值
#(a)expr一步完成计算
$ expr `expr 2 + 3` \* 4
20
#(b)采用$[运算式]方式
# S=$[(2+3)*4]
# echo $S

5. 条件判断

  1. 基本语法

[ condition ](注意condition前后要有空格)

注意:条件非空即为true,[xubh]返回true,[] 返回false。

  1. 常用判断条件
  • 两个整数之间比较

= 字符串比较

-lt 小于(less than) -le 小于等于(less equal)

-eq 等于(equal) -gt 大于(greater than)

-ge 大于等于(greater equal) -ne 不等于(Not equal)

  • 按照文件权限进行判断

-r 有读的权限(read)

-w 有写的权限(write)

-x 有执行的权限(execute)

  • 按照文件类型进行判断

-f 文件存在并且是一个常规的文件(file)

-e 文件存在(existence)

-d 文件存在并是一个目录(directory)

  1. 案例实操
#(1)23是否大于等于22
$ [ 23 -ge 22 ]
$ echo $?
0
#(2)helloworld.sh是否具有写权限
$ [ -w helloworld.sh ]
$ echo $?
0
#(3)/home/xubh/cls.txt目录中的文件是否存在
$ [ -e /home/xubh/cls.txt ]
$ echo $?
1
#(4)多条件判断(&& 表示前一条命令执行成功时,才执行后一条命令,|| 表示上一条命令执行失败后,才执行下一条命令)
$ [ condition ] && echo OK || echo notok
OK
$ [ condition ] && [ ] || echo notok
notok

6. 流程控制

if 判断

  1. 基本语法
if [expression]; then
    will execute only if expression is true
else
    will execute if expression is false
fi

​ 注意事项:

  • [ 条件判断式 ],中括号和条件判断式之间必须有空格

  • if后要有空格

  1. 案例实操

    • 输入一个数字,如果是1,则输出banzhang zhen shuai,如果是2,则输出cls zhen mei,如果是其它,什么也不输出。
$ touch if.sh
$ vim if.sh

#!/bin/bash
if [ $1 -eq "1" ]
then
        echo "banzhang zhen shuai"
elif [ $1 -eq "2" ]
then
        echo "cls zhen mei"
fi

statement1 && statement2  # 两个语句都为真
statement1 || statement2  # 至少一个语句为真

str1=str2       # str1 匹配 str2
str1!=str2      # str1 不匹配 str2
str1<str2       # str1 小于 str2
str1>str2       # str1 大于 str2
-n str1         # str1 不是 null (长度大于 0)
-z str1         # str1 是 null (长度为 0)

-a file         # 文件存在
-d file         # 文件存在而且是目录
-e file         # 文件存在,跟 -a 一样
-f file         # 文件存在,而且是常规文件(不是目录或者其他特殊类型的文件)
-r file         # 你有读权限
-s file         # 文件存在而且不为空
-w file         # 你有写权限
-x file         # 你对文件有执行权限,如果 file 是目录的话,你对它有搜索权限
-N file         # 从上次读之后文件被修改过
-O file         # 你是文件所有者
-G file         # 文件的 group ID 跟你的 group ID (或之一,如果你在很多分组里)相同

file1 -nt file2     # file1 比 file2 更新
file1 -ot file2     # file1 比 file2 更老

-lt     # 小于
-le     # 小于等于
-eq     # 等于
-ge     # 大于等于
-gt     # 大于
-ne     # 不等于

$ chmod 777 if.sh 
$ ./if.sh 1
banzhang zhen shuai

case 语句

  1. 基本语法

case $变量名 in

"值1")

​ 如果变量的值等于值1,则执行程序1

​ ;;

"值2")

​ 如果变量的值等于值2,则执行程序2

​ ;;

…省略其他分支…

*)

​ 如果变量的值都不是以上的值,则执行此程序

​ ;;

esac

注意事项:

  • case行尾必须为单词“in”,每一个模式匹配必须以右括号“)”结束。
  • 双分号“;;”表示命令序列结束,相当于java中的break。
  • 最后的“*)”表示默认模式,相当于java中的default。
  1. 案例实操

    • 输入一个数字,如果是1,则输出banzhang,如果是2,则输出cls,如果是其它,输出renyao。
$ touch case.sh
$ vim case.sh

!/bin/bash

case $1 in
"1")
        echo "banzhang"
;;

"2")
        echo "cls"
;;
*)
        echo "renyao"
;;
esac

$ chmod 777 case.sh
$ ./case.sh 1
1

for 循环

  1. 基本语法1

for (( initialisation ; ending condition ; update ))
do
statements...
done
```

  1. 案例实操

    • 从1加到100
$ touch for1.sh
$ vim for1.sh

#!/bin/bash

s=0
for((i=0;i<=100;i++))
do
        s=$[$s+$i]
done
echo $s

$ chmod 777 for1.sh 
$ ./for1.sh 
“5050”
  1. 基本语法2
for name [in list]
do
  statements that can use $name
done
  1. 案例实操
    1. 打印所有输入参数
$ touch for2.sh
$ vim for2.sh

#!/bin/bash
#打印数字

for i in $*
    do
      echo "ban zhang love $i "
    done

$ chmod 777 for2.sh 
$ bash for2.sh cls xz bd
ban zhang love cls
ban zhang love xz
ban zhang love bd
  1. 比较*和@区别

(a)*和@都表示传递给函数或脚本的所有参数,不被双引号“”包含时,都以12 …$n的形式输出所有参数。

$ touch for.sh
$ vim for.sh

#!/bin/bash 

for i in $*
do
      echo "ban zhang love $i "
done

for j in $@
do      
        echo "ban zhang love $j"
done

$ bash for.sh cls xz bd
ban zhang love cls 
ban zhang love xz 
ban zhang love bd 
ban zhang love cls
ban zhang love xz
ban zhang love bd

(b)当它们被双引号“”包含时,“*”会将所有的参数作为一个整体,以“1 2 …n”的形式输出所有参数;“@”会将各个参数分开,以“1” “2”…”n”的形式输出所有参数。

$ vim for.sh

#!/bin/bash 

for i in "$*" 
#$*中的所有参数看成是一个整体,所以这个for循环只会循环一次 
        do 
                echo "ban zhang love $i"
        done 

for j in "$@" 
#$@中的每个参数都看成是独立的,所以“$@”中有几个参数,就会循环几次 
        do 
                echo "ban zhang love $j" 
done

$ chmod 777 for.sh
$ bash for.sh cls xz bd
ban zhang love cls xz bd
ban zhang love cls
ban zhang love xz
ban zhang love bd

while 循环

  1. 基本语法
while condition; do
  statements
done
  1. 案例实操
    1. 从1加到100
$ touch while.sh
$ vim while.sh

#!/bin/bash
s=0
i=1
while [ $i -le 100 ]
do
        s=$[$s+$i]
        i=$[$i+1]
done

echo $s

$ chmod 777 while.sh 
$ ./while.sh 
5050

7. read读取控制台输入

  1. 基本语法

​ read(选项)(参数)

​ 选项:

-p:指定读取值时的提示符;

-t:指定读取值时等待的时间(秒)。

参数

​ 变量:指定读取值的变量名

  1. 案例实操

​ (1)提示7秒内,读取控制台输入的名称

$ touch read.sh
$ vim read.sh

#!/bin/bash

read -t 7 -p "Enter your name in 7 seconds " NAME
echo $NAME

$ ./read.sh 
Enter your name in 7 seconds xiaoze
xiaoze

8. 函数

系统函数

  1. basename基本语法

basename [string / pathname] [suffix] (功能描述:basename命令会删掉所有的前缀包括最后一个(‘/’)字符,然后将字符串显示出来。

选项:

suffix为后缀,如果suffix被指定了,basename会将pathname或string中的suffix去掉。

  1. 案例实操
  • 截取该/home/xubh/banzhang.txt路径的文件名称
$ basename /home/xubh/banzhang.txt 
banzhang.txt
$ basename /home/xubh/banzhang.txt .txt
banzhang
  1. dirname基本语法

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

  1. 案例实操

    • 获取banzhang.txt文件的路径
$ dirname /home/xubh/banzhang.txt 
/home/xubh

自定义函数

  1. 基本语法

[ function ] funname[()]

{

​ Action;

​ [return int;]

}

funname

  1. 经验技巧

    ​ 1.必须在调用函数地方之前,先声明函数,shell脚本是逐行运行。不会像其它语言一样先编译。

    ​ 2.函数返回值,只能通过$?系统变量获得,可以显示加:return返回,如果不加,将以最后一条命令运行结果,作为返回值。return后跟数值n(0-255)

  2. 案例实操

    计算两个输入参数的和

$ touch fun.sh
$ vim fun.sh

#!/bin/bash
function sum()
{
    s=0
    s=$[ $1 + $2 ]
    echo "$s"
}

read -p "Please input the number1: " n1;
read -p "Please input the number2: " n2;
sum $n1 $n2;

$ chmod 777 fun.sh
$ ./fun.sh 
Please input the number1: 2
Please input the number2: 5
7
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容