二、shell初步学习(基本语法)

本文介绍了Shell脚本的基础知识,包括变量的定义、使用、只读变量、删除变量和变量类型;字符串的定义、拼接、长度、子字符串和查找;数组的定义和操作;注释的使用;以及Shell的运算符,如算术、关系、布尔、字符串和文件测试运算符。此外,还讲解了如何在Shell中进行条件判断、循环控制,以及常用的echo和printf命令。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、变量

在几乎所有的计算机语言中都有变量,shell脚本开发中也有变量,它是指在一个过程中可以指定变化的量

1.1、变量的定义

shell脚本中定义变量时,变量名不加美元符号$,不同于PHP语言,

hello="hellp world"

注意,变量名和等号之间不能有空格,变量名定义时需要遵循相关的规则(同python等其它语言)

1.2、变量的使用

shell脚本中使用一个已经定义过的变量时,需要在变量名前面添加美元符号$,如:

#!/bin/bash

hello="hello world"

echo $hell0

当然,可以使用花括号将变量名括起来,告诉解释器是一个变量,这在一些特殊的地方很好用。例如:

for item in "one two three"
    echo "${item}_apple"

此时使用花括号是最好的选择,防止解释器区分不了变量的边界

1.3、只读变量

在python等计算机语言中,有常量,在shell脚本中可以定义只读变量,表示该变量一旦定义,后续操作只能进行读操作,不能进行写操作 。使用readonly进行指定,如:

#!/bin/bash

myUrl="https://www.google.com"
readonly myUrl
myUrl="https://www.baidu.com"

运行脚本会出现错误提示,表示该变量为 read only

1.4、删除变量

对于变量的释放,即删除,则使用unset关键字,注意两点(1、只读变量不可进行删除。2、删除后变量无法使用,即不存在)

#!/bin/sh

name="zhangsan"
unset name
echo $name

运行后不会出现任何输出

1.5、变量的类型

shell脚本中会涉及到局部变量、环境变量和shell变量

  1. 局部变量:在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量。
  2. 环境变量:所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量。
  3. shell变量:shell中的特殊变量,为保证shell的正常运行而定义,一部分为局部变量,一部分为环境变量

2、shell字符串

shell脚本中最常用的就是字符串和数字,可以使用单引号‘’,双引号“”及不用引号

2.1、字符串的定义

#!/bin/bash

one='one'
two="two"
three=something

拼接字符串

#!/bin/bash

one="one"
# 使用双引号拼接
greeting="hello, "$one" !"
greeting_1="hello, ${one} !"
echo $greeting  $greeting_1


# 使用单引号拼接
greeting_2='hello, '$one' !'
greeting_3='hello, ${one} !'
echo $greeting_2  $greeting_3

输出结果为

hello, one ! hello, one !
hello, one ! hello, ${one} !

获取字符串长度

#!/bin/bash

one="hello world"

echo ${#one}  # 输出11

read -n 1  # 确保界面不退出

提取子字符串

以下实例从字符串第 3 个字符开始截取 5 个字符:

格式:${变量名:索引位置:截取个数}

#!/bin/bash

one="hello world"

echo ${one:2:5}  # 输出llo w,空格也会被打印

read -n 1  # 确保界面不退出

注意:第一个索引位置为0

查找子字符串

查找字符 l 的位置(查找到的第一个值的位置):

#!/bin/bash

one="hello world"

echo `expr index "$one" l` # 输出3,此时输出的并非索引

read -n 1  # 确保界面不退出

注意:` 是反引号,而不是单引号 '

3、shell脚本数组

对于shell脚本中的数组来说,与c语言中的数组基本一致,可以定义数字数组、字符串数组等

3.1、数组的定义

数组的定义分为三种:

①使用空格符分开

②使用回车符分开

③利用索引直接进行定义

#!/bin/bash

# 定义数组

# 使用空格分开
two=(value0 value1 value2 value3)
one=(1 2 3 4)

# 使用回车符分开
three=(
1
2
3
4
)

# 直接进行定义
four[0]=1
four[1]=2
four[2]=3
four[3]=4

读取数组

读取数组元素值的一般格式是:${数组名[下标]},与变量一致,获取时需要加美元符号$,数组名指的是数组的第一个元素,需要哪个元素要指定相应的索引位置,如:

#!/bin/bash

one=(1 2 3 4)
echo "使用数组名输出$one"
echo "使用数组名输出${one}"

# 指定数组索引
echo "指定数组索引输出${one[1]}"

read -n 1

注意:此处输出使用双引号"",单双引号输出有何不同可以自己试试

输出如下:

使用数组名输出1
使用数组名输出1
指定数组索引输出2

对于整个数组的输出,可以进行遍历,此处初步介绍一下printf,类似c语言中printf()函数,shell脚本中也有类似命令printf,作用与echo命令一致,唯一不同在于echo输出时会自动输出回车符,printf则不会自动输出回车

#!/bin/bash

# @Author: admin
# @Date:   2021-04-26 17:27:56
# @Last Modified by:   admin
# @Last Modified time: 2021-04-27 09:55:41

one=(1 2 3 4)
echo "使用数组名输出$one"
echo "使用数组名输出${one}"

# 指定数组索引
echo "指定数组索引输出${one[1]}"

for item in ${one[@]}; do
	printf $item
done
read -n 1

输出如下:

使用数组名输出1
使用数组名输出1
指定数组索引输出2
1234

当然也可以直接输出数组,则使用@或*符号,例如${one[@]}

#!/bin/bash

# @Author: admin
# @Date:   2021-04-26 17:27:56
# @Last Modified by:   admin
# @Last Modified time: 2021-04-27 09:59:36

one=(1 2 3 4)

echo ${one[@]}
echo ${one[*]}

read -n 1

输出如下:

1 2 3 4
1 2 3 4

获取数组的长度

获取数组长度的方法与获取字符串长度的方法相同

#!/bin/bash

one=(1 2 3 4)

echo ${#one[@]}  # 输出4

read -n 1

单个元素的长度获取同字符串

4、shell脚本注释

对于shell脚本来说,注释是必不可少的,主要起到解释说明的作用,在shell脚本中使用#符号来注释单行命令,使用 :<<EOF 注释内容... 注释内容... 注释内容... EOF来注释多行命令,如下:

#!/bin/bash

one=(1 2 3 4)
:<<EOF
echo ${#one[@]}  # 输出4
echo ${#one[@]}  # 输出4
echo ${#one[@]}  # 输出4
echo ${#one[@]}  # 输出4
echo ${#one[@]}  # 输出4
echo ${#one[@]}  # 输出4
EOF

echo ${#one[*]}  # 输出4

read -n 1

EOF可以使用其它符号替换

#!/bin/bash

one=(1 2 3 4)
:<<!
echo ${#one[@]}  # 输出4
echo ${#one[@]}  # 输出4
echo ${#one[@]}  # 输出4
echo ${#one[@]}  # 输出4
echo ${#one[@]}  # 输出4
echo ${#one[@]}  # 输出4
!

echo ${#one[*]}  # 输出4

read -n 1

单行注释

#!/bin/bash

one=(1 2 3 4)

# echo ${#one[@]}  # 输出4
# echo ${#one[@]}  # 输出4
# echo ${#one[@]}  # 输出4
# echo ${#one[@]}  # 输出4
echo ${#one[@]}  # 输出4


echo ${#one[*]}  # 输出4

read -n 1

5、Shell 运算符

Shell 和其他编程语言一样,支持多种运算符,包括:

  • 算数运算符
  • 关系运算符
  • 布尔运算符
  • 字符串运算符
  • 文件测试运算符

原生bash不支持简单的数学运算,需要通过其他命令来实现,例如 expr。

expr 是一款表达式计算工具,使用它能完成表达式的求值操作。

注意:使用expr时,需要使用反引号`括起来

#!/bin/bash

one=(1 2 3 4)

# value=${one[0]}+${one[3]}
# echo $value  # 此时输出1+4的字符串

value=`expr ${one[0]} + ${one[3]}`
echo $value  # 此时输出5

read -n 1

两点注意:

  • 表达式和运算符之间要有空格,例如 2+2 是不对的,必须写成 2 + 2,这与我们熟悉的大多数编程语言不一样。
  • 完整的表达式要被 ` ` 包含,注意这个字符不是常用的单引号

5.1、算术运算符

下表列出了常用的算术运算符,假定变量 a 为 10,变量 b 为 20:

运算符说明举例
+加法`expr $a + $b` 结果为 30。
-减法`expr $a - $b` 结果为 -10。
*乘法`expr $a \* $b` 结果为  200。
/除法`expr $b / $a` 结果为 2。
%取余`expr $b % $a` 结果为 0。
=赋值a=$b 将把变量 b 的值赋给 a。
==相等。用于比较两个数字,相同则返回 true。[ $a == $b ] 返回 false。
!=不相等。用于比较两个数字,不相同则返回 true。[ $a != $b ] 返回 true。

注意:条件表达式要放在方括号之间,并且要有空格,例如: [$a==$b] 是错误的,必须写成 [ $a == $b ]。具体示例可自己测试

5.2、关系运算符

关系运算符只支持数字,不支持字符串,除非字符串的值是数字。

下表列出了常用的关系运算符,假定变量 a 为 10,变量 b 为 20:

运算符说明举例
-eq检测两个数是否相等,相等返回 true。[ $a -eq $b ] 返回 false。
-ne检测两个数是否不相等,不相等返回 true。[ $a -ne $b ] 返回 true。
-gt检测左边的数是否大于右边的,如果是,则返回 true。[ $a -gt $b ] 返回 false。
-lt检测左边的数是否小于右边的,如果是,则返回 true。[ $a -lt $b ] 返回 true。
-ge检测左边的数是否大于等于右边的,如果是,则返回 true。[ $a -ge $b ] 返回 false。
-le检测左边的数是否小于等于右边的,如果是,则返回 true。[ $a -le $b ] 返回 true。

5.3、布尔运算符

下表列出了常用的布尔运算符,假定变量 a 为 10,变量 b 为 20:

运算符说明举例
!非运算,表达式为 true 则返回 false,否则返回 true。[ ! false ] 返回 true。
-o或运算,有一个表达式为 true 则返回 true。[ $a -lt 20 -o $b -gt 100 ] 返回 true。
-a与运算,两个表达式都为 true 才返回 true。[ $a -lt 20 -a $b -gt 100 ] 返回 false。

5.4、逻辑运算符

以下介绍 Shell 的逻辑运算符,假定变量 a 为 10,变量 b 为 20:

运算符说明举例
&&逻辑的 AND[[ $a -lt 100 && $b -gt 100 ]] 返回 false
||逻辑的 OR[[ $a -lt 100 || $b -gt 100 ]] 返回 true

5.5、字符串运算符

下表列出了常用的字符串运算符,假定变量 a 为 "abc",变量 b 为 "efg":

运算符说明举例
=检测两个字符串是否相等,相等返回 true。[ $a = $b ] 返回 false。
!=检测两个字符串是否不相等,不相等返回 true。[ $a != $b ] 返回 true。
-z检测字符串长度是否为0,为0返回 true。[ -z $a ] 返回 false。
-n检测字符串长度是否不为 0,不为 0 返回 true。[ -n "$a" ] 返回 true。
$检测字符串是否为空,不为空返回 true。[ $a ] 返回 true。

5.6、文件测试运算符

文件测试运算符用于检测 Unix 文件的各种属性。

属性检测描述如下:

操作符说明举例
-b file检测文件是否是块设备文件,如果是,则返回 true。[ -b $file ] 返回 false。
-c file检测文件是否是字符设备文件,如果是,则返回 true。[ -c $file ] 返回 false。
-d file检测文件是否是目录,如果是,则返回 true。[ -d $file ] 返回 false。
-f file检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。[ -f $file ] 返回 true。
-g file检测文件是否设置了 SGID 位,如果是,则返回 true。[ -g $file ] 返回 false。
-k file检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。[ -k $file ] 返回 false。
-p file检测文件是否是有名管道,如果是,则返回 true。[ -p $file ] 返回 false。
-u file检测文件是否设置了 SUID 位,如果是,则返回 true。[ -u $file ] 返回 false。
-r file检测文件是否可读,如果是,则返回 true。[ -r $file ] 返回 true。
-w file检测文件是否可写,如果是,则返回 true。[ -w $file ] 返回 true。
-x file检测文件是否可执行,如果是,则返回 true。[ -x $file ] 返回 true。
-s file检测文件是否为空(文件大小是否大于0),不为空返回 true。[ -s $file ] 返回 true。
-e file检测文件(包括目录)是否存在,如果是,则返回 true。[ -e $file ] 返回 true。

其他检查符:

  • -S: 判断某文件是否 socket。
  • -L: 检测文件是否存在并且是一个符号链接。
#!/bin/bash
file="D:/test.sh"
if [ -r $file ]
then
   echo "文件可读"
else
   echo "文件不可读"
fi
if [ -w $file ]
then
   echo "文件可写"
else
   echo "文件不可写"
fi
if [ -x $file ]
then
   echo "文件可执行"
else
   echo "文件不可执行"
fi
if [ -f $file ]
then
   echo "文件为普通文件"
else
   echo "文件为特殊文件"
fi
if [ -d $file ]
then
   echo "文件是个目录"
else
   echo "文件不是个目录"
fi
if [ -s $file ]
then
   echo "文件不为空"
else
   echo "文件为空"
fi
if [ -e $file ]
then
   echo "文件存在"
else
   echo "文件不存在"
fi

read -n 1

输出:

文件不可读
文件不可写
文件不可执行
文件为特殊文件
文件不是个目录
文件为空
文件不存在

在此介绍一下if条件判断语句,shell脚本中条件判断语句格式如下:

if [条件 ]
then
   执行命令1

else

   执行命令2
fi  # 结束

条件符合执行命令1,否则执行命令2

6、Shell 传递参数

在shell脚本中可以在执行的时候传递参数,在脚本中使用美元符号$n进行获取使用,n表示传递的参数序号,如下:

#!/bin/bash

echo "Shell 传递参数实例!";
echo "执行的文件名:$0";
echo "第一个参数为:$1";
echo "第二个参数为:$2";
echo "第三个参数为:$3";

read -n 1

注意在运行该shell脚本时,需要传入参数,如:hello.sh 1 2 3。1 2 3为外部传入的参数,$0表示执行的文件名(包含路径)

输出:

Shell 传递参数实例!
执行的文件名:D:\hello.sh
第一个参数为:1
第二个参数为:2
第三个参数为:3

特殊字符用来处理参数:

参数处理说明
$#传递到脚本的参数个数
$*以一个单字符串显示所有向脚本传递的参数。
如"$*"用「"」括起来的情况、以"$1 $2 … $n"的形式输出所有参数。
$$脚本运行的当前进程ID号
$!后台运行的最后一个进程的ID号
$@与$*相同,但是使用时加引号,并在引号中返回每个参数。
如"$@"用「"」括起来的情况、以"$1" "$2" … "$n" 的形式输出所有参数。
$-显示Shell使用的当前选项,与set命令功能相同。
$?显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。

7、shell命令

shell脚本中经常涉及到3个命令关键字

①echo,用于字符串的输出,自动输出回车符。

②printf,同样用于字符串的输入,但不会自动输出回车符

③用于检查某个条件是否成立,它可以进行数值、字符和文件三个方面的测试。

7.1、echo命令

用于字符串的输出,自动输出回车符。命令格式:echo string

显示普通字符串

输出:

hello world
hello world

注意:可以使用双引号或者不使用引号

显示转义字符

对于字符串来讲,有一部分特殊的符号有特别的代表,为了输出这种原本的特殊符号,需要进行转义,一般在该符号前加上反斜杠\,如下:

#!/bin/bash

# 输出"hello world"
echo "\"hello world\""

echo hello world

read -n 1

输出:

"hello world"
hello world

显示变量

在输入变量,运行shell脚本后,将变量具体的值显示出来

#!/bin/bash

read name

echo "${name} is my baby" # 注意此处是双引号

read -n 1 # 确保运行完不进行退出

显示结果:

OK
OK is my baby

显示换行

如果需要自定义换行,则需要换行符\n,但需要注意的是,一般都需要-e来表示开启换行

#!/bin/bash

read name

echo -e "${name} is my baby \n hahaha" # 注意此处是双引号

read -n 1 # 确保运行完不进行退出

显示结果

ok
ok is my baby
 hahaha

显示不换行

对于多个echo命令,如果需要不换行显示,则需要添加不换行符\c,需要打开转义

#!/bin/bash

read name

echo -e "${name} is my baby \c" # 注意此处是双引号
echo -e "hahaha"

read -n 1 # 确保运行完不进行退出

显示结果

ok
ok is my baby hahaha

将结果输出指定的文件中

使用>符号则会将需要打印的结果输出到指定的文件中

#!/bin/bash

read name

echo -e "${name} is my baby">myfile # 注意此处是双引号
echo -e "hahaha"

read -n 1 # 确保运行完不进行退出

原样输出字符串,不进行转义或取变量(用单引号)

echo '$name\"'   #注意此处使用单引号

显示命令执行结果

echo `date`

注意: 这里使用的是反引号 `, 而不是单引号 '。结果将显示当前日期

7.2、printf命令

printf命令,作用与echo命令都是进行输出,但printf有更加强大的功能,能够格式化输出指定格式的数据,(注意:echo会自动输出空格,printf不会自动输出空格)

#!/bin/bash


printf "%-10s %-8s %-4s\n" 姓名 性别 体重kg  
printf "%-10s %-8s %-4.2f\n" 张三 男 66.1234
printf "%-10s %-8s %-4.2f\n" 里斯 男 48.6543
printf "%-10s %-8s %-4.2f\n" 王五 女 47.9876

read -n 1 # 确保运行完不进行退出

输出结果:

姓名     性别   体重kg
张三     男      66.12
里斯     男      48.65
王五     女      47.99

详细介绍:

%s 输出一个字符串,%d 整型输出,%c 输出一个字符,%f 输出实数,以小数形式输出。%-10s 指一个宽度为 10 个字符(- 表示左对齐,没有则表示右对齐),任何字符都会被显示在 10 个字符宽的字符内,如果不足则自动以空格填充,超过也会将内容全部显示出来。%-4.2f 指格式化为小数,其中 .2 指保留2位小数。(与C语言中的printf()函数基本一致)

printf 的转义序列

序列说明
\a警告字符,通常为ASCII的BEL字符
\b后退
\c抑制(不显示)输出结果中任何结尾的换行字符(只在%b格式指示符控制下的参数字符串中有效),而且,任何留在参数里的字符、任何接下来的参数以及任何留在格式字符串中的字符,都被忽略
\f换页(formfeed)
\n换行
\r回车(Carriage return)
\t水平制表符
\v垂直制表符
\\一个字面上的反斜杠字符
\ddd表示1到3位数八进制值的字符。仅在格式字符串中有效
\0ddd表示1到3位的八进制值字符

7.3、test 命令

Shell中的 test 命令用于检查某个条件是否成立,它可以进行数值、字符和文件三个方面的测试。

字符串

参数说明
=等于则为真
!=不相等则为真
-z 字符串字符串的长度为零则为真
-n 字符串字符串的长度不为零则为真
#!/bin/bash

num1="test"
num2="test"
if test $num1 = $num2
then
    echo '两个字符串相等!'
else
    echo '两个字符串不相等!'
fi

read -n 1 # 确保运行完不进行退出

输出:

两个字符串相等!

数值

参数说明
-eq等于则为真
-ne不等于则为真
-gt大于则为真
-ge大于等于则为真
-lt小于则为真
-le小于等于则为真

数值与字符串不同的是数值运算时需要加上[]中括号

#!/bin/bash

num1=100
num2=100
if test $[num1] -eq $[num2]
then
    echo '两个数相等!'
else
    echo '两个数不相等!'
fi

echo $[num1+num2]
read -n 1 # 确保运行完不进行退出

结果:

两个数相等!
200

文件测试

参数说明
-e 文件名如果文件存在则为真
-r 文件名如果文件存在且可读则为真
-w 文件名如果文件存在且可写则为真
-x 文件名如果文件存在且可执行则为真
-s 文件名如果文件存在且至少有一个字符则为真
-d 文件名如果文件存在且为目录则为真
-f 文件名如果文件存在且为普通文件则为真
-c 文件名如果文件存在且为字符型特殊文件则为真
-b 文件名如果文件存在且为块特殊文件则为真

Shell 还提供了与( -a )、或( -o )、非( ! )三个逻辑操作符用于将测试条件连接起来,其优先级为: ! 最高, -a 次之, -o 最低。

7.4、Shell 流程控制

对于一种计算机语言来说,流程中必不可少的,流程控制是必须有的。在shell中有

  • if

  • if else

  • if else-if else

  • for 循环

  • while 语句

  • until 循环

  • case ... esac

  • break命令

  • continue

7.4.1 if

if conditions
then
    ...
fi

7.4.2 if else

if conditions
then
    ...
else
    ,,,
fi

7.4.3 if else-if else

if condition1
then
    aaa
elif condition2 
then 
    bbb
else
    ccc
fi

7.4.4 for 循环

for var in aaa bbb ccc
do
    ...
done

7.4.5 while 语句

while condition
do
    ...
done

7.4.6 until 循环

until condition
do
    ...
done

7.4.7 case ... esac多选择语句

case var in
data1)
    command1
    command2
    ...
    ;;
data2)
    command1
    command2
    ...
    ;;
esac

7.4.8 break 和 continue

        break跳出循环,continue跳出本次循环

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值