【AcWing-Linux】03. Shell
Shell
一、Shell简介
shell是我们通过命令行与操作系统沟通的语言。
shell是一种脚本语言,通过对应的脚本解释器解释执行,一般作为内置于操作系统的应用程序向用户提供访问操作系统内核的服务。
shell脚本(shell script)可以直接在命令行中执行,也可以将一套逻辑组织成一个文件,方便复用。
二、Shell环境
Shell编程跟JavaScript、Python编程一样,只要有一个能编写代码的文本编辑器和一个能解释执行的脚本解释器就可以了。
Linux中常见的shell种类众多,常见的有:
- Bourne Shell(/usr/bin/sh或/bin/sh)
- Bourne Again Shell(/bin/bash)
- C Shell(/usr/bin/csh)
- K Shell(/usr/bin/ksh)
- zsh
- ....
Linux系统中一般默认使用bash,所以接下来讲解bash中的语法。
文件开头需要写#! /bin/bash
,指明bash为脚本解释器。
#! 告诉系统其后路径所指定的程序即是解释此脚本文件的Shell程序。
三、第一个Shell脚本
打开文本编辑器(可以使用vi/vim来创建文件),新建一个test.sh,扩展名为.sh(扩展名不会影响脚本执行,见名之意即可)。
新建一个test.sh
文件,内容如下:
#! /bin/bash
echo "Hello World!"
#! 是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行,即使用哪一种Shell。
echo命令用于向窗口输出文本。
运行方式:
- 作为可执行文件
acs@9e0ebfcd82d7:~$ chmod +x test.sh # 使脚本具有可执行权限
acs@9e0ebfcd82d7:~$ ./test.sh # 当前路径下执行
Hello World! # 脚本输出
acs@9e0ebfcd82d7:~$ /home/acs/test.sh # 绝对路径下执行
Hello World! # 脚本输出
acs@9e0ebfcd82d7:~$ ~/test.sh # 家目录路径下执行
Hello World! # 脚本输出
注意:一定要写成 ./test.sh,而不是 test.sh,运行其它二进制的程序也一样,直接写test.sh,linux系统会去PATH里寻找有没有叫test.sh的,而只有/bin, /sbin, /usr/bin,/usr/sbin 等在 PATH 里,你的当前目录通常不在 PATH 里,所以写成 test.sh 是会找不到命令的,要用 ./test.sh 告诉系统说,就在当前目录找。
- 作为解释器参数
acs@9e0ebfcd82d7:~$ bash test.sh
Hello World! # 脚本输出
四、注释
单行注释
每行中#
之后的内容均是注释。
# 这是一行注释
echo 'Hello World' # 这也是注释
多行注释
格式:
:<<EOF
第一行注释
第二行注释
第三行注释
EOF
其中EOF
可以换成其它任意字符串。例如:
:<<abc
第一行注释
第二行注释
第三行注释
abc
:<<!
第一行注释
第二行注释
第三行注释
!
五、变量
在Shell编程中,变量是用于存储数据值的名称。
定义变量
在定义变量时,变量名不加美元符号$,如:
variable_name=value
注意:变量名和等号之间不能有空格。
变量名的命名遵循如下规则:
- 只包含字母、数字和下划线:变量名可以包含字母(大小写敏感)、数字和下划线_,不能包含其他特殊字符。
- 不能以数字开头: 变量名不能以数字开头,但可以包含数字。
- 避免使用 Shell 关键字: 不要使用Shell的关键字(例如 if、then、else、fi、for、while 等)作为变量名,以免引起混淆。
- 使用大写字母表示常量: 习惯上,常量的变量名通常使用大写字母,例如 PI=3.14。
- 避免使用特殊符号: 尽量避免在变量名中使用特殊符号,因为它们可能与 Shell 的语法产生冲突。
- 避免使用空格: 变量名中不应该包含空格,因为空格通常用于分隔命令和参数。
使用变量
使用变量,需要加上$
符号,或者${}
符号。花括号是可选的,主要为了帮助解释器识别变量边界。
name=yxc
echo $name # 输出yxc
echo ${name} # 输出yxc
echo ${name}acwing # 输出yxcacwing
注意:使用变量的时候才加美元符号$。
只读变量
使用readonly
或者declare
可以将变量定义为只读变量,只读变量的值不能被改变。
#! /bin/bash
myUrl="http://www.baidu.com"
readonly myUrl
declare -r myUrl # 两种写法均可
myUrl="http://www.google.com" # 会报错,因为此时myUrl只读
删除变量
使用unset
可以删除变量。
variable_name=value
unset variable_name
echo $variable_name # 输出空行
注意:变量被删除后不能再次使用。unset命令不能删除只读变量。
变量类型
- 自定义变量(局部变量)
子进程不能访问的变量 - 环境变量(全局变量)
子进程可以访问的变量
自定义变量改成环境变量:
acs@9e0ebfcd82d7:~$ name=yxc # 定义变量
acs@9e0ebfcd82d7:~$ export name # 第一种方法
acs@9e0ebfcd82d7:~$ declare -x name # 第二种方法
环境变量改为自定义变量:
acs@9e0ebfcd82d7:~$ export name=yxc # 定义环境变量
acs@9e0ebfcd82d7:~$ declare +x name # 改为自定义变量
字符串
字符串可以用单引号'
,也可以用双引号"
,也可以不用引号。
单引号字符串的限制:
- 单引号中的内容会原样输出,单引号字符串中的变量是无效的;
- 单引号字符串中不能出现单独一个单引号(对单引号使用转移字符后也不行),但可成对出现,作为字符串拼接使用;
双引号的优点:
- 双引号里可以有变量;
- 双引号里可以出现转义字符;
name=yxc # 不用引号
echo 'hello, $name \"hh\"' # 单引号字符串,输出 hello, $name \"hh\"
echo "hello, $name \"hh\"" # 双引号字符串,\"hh\" 中的反斜杠被用来转义双引号,输出结果中会包含双引号,输出 hello, yxc "hh"
获取字符串长度
name="yxc"
echo ${#name} # 输出3
提取子串
name="hello, yxc"
echo ${name:0:5} # 提取从0开始的5个字符,也可以理解为索引[0, 5) 输出hello
六、默认变量
文件参数变量
在执行shell脚本时,可以向脚本传递参数。$1
是第一个参数,$2
是第二个参数,以此类推。特殊的,$0
是文件名(包含路径)。例如:
创建文件test.sh
:
#! /bin/bash
echo "文件名:"$0
echo "第一个参数:"$1
echo "第二个参数:"$2
echo "第三个参数:"$3
echo "第四个参数:"$4
然后执行该脚本:
acs@9e0ebfcd82d7:~$ chmod +x test.sh
acs@9e0ebfcd82d7:~$ ./test.sh 1 2 3 4
文件名:./test.sh
第一个参数:1
第二个参数:2
第三个参数:3
第四个参数:4
其它参数相关变量
参数 | 说明 |
---|---|
$# |
代表文件传入的参数个数,如上例中值为4 |
$* |
由所有参数构成的用空格隔开的字符串,如上例中值为"$1 $2 $3 $4" |
$@ |
每个参数分别用双引号括起来的字符串,如上例中值为"$1" "$2" "$3" "$4" |
$$ |
脚本当前运行的进程ID |
$? |
上一条命令的退出状态(注意不是stdout,而是exit code)。0表示正常退出,其他值表示错误 |
$(command) |
返回command 这条命令的stdout(可嵌套)(即输入这条语句后显示出的结果) |
`command` | 返回command 这条命令的stdout(不可嵌套) |
创建文件test1.sh
:
#! /bin/bash
echo "文件名:"$0
echo "第一个参数:"$1
echo "第二个参数:"$2
echo "第三个参数:"$3
echo "第四个参数:"$4
echo $# # 4
echo $* # 1 2 3 4
echo $@ # 1 2 3 4
echo $$ # 74(脚本当前运行的进程ID)
echo $? # 0(表示正常退出)
echo $(ls) # dir_a dir_b dir_C homework test.sh test.txt (返回ls这条命令的stdout)
echo `ls` # dir_a dir_b dir_C homework test.sh test.txt (返回ls这条命令的stdout)
七、数组
bash支持一维数组(不支持多维数组),并且没有限定数组的大小。
类似于C语言,数组元素的下标由0开始编号。获取数组中的元素要利用下标,下标可以是整数或算数表达式,其值应大于或的等于0。
定义
数组用小括号表示,元素之间用空格隔开。例如:
# 数组名=(值1 值2 值3... 值n)
array=(1 abc "def" yxc)
也可以直接定义数组中某个元素的值:
array[0]=1
array[1]=abc
array[2]="def"
array[3]=yxc
读取数组中某个元素的值
格式:
# ${数组名[下标]}
${array[index]}
例如:
array=(1 abc "def" yxc)
echo ${array[0]} # 1
echo ${array[1]} # abc
echo ${array[2]} # "def"
echo ${array[3]} # yxc
注意:可以不使用连续的下标,而且下标的范围没有限制。
读取整个数组
格式:
${array[@]} # 第一种写法
${array[*]} # 第二种写法
例如:
array=(1 abc "def" yxc)
echo ${array[@]} # 第一种写法 1 abc "def" yxc
echo ${array[*]} # 第二种写法 1 abc "def" yxc
数组长度
类似于字符串
${#array[@]} # 第一种写法
${#array[*]} # 第二种写法
例如:
array=(1 abc "def" yxc)
echo ${#array[@]} # 第一种写法 # 4
echo ${#array[*]} # 第二种写法 # 4
echo ${#array} # 等价于 echo ${#array[0]} 表示数组第一个元素的长度
本文作者:Ac_c0mpany丶
本文链接:https://www.cnblogs.com/keyongkang/p/17869466.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
2022-12-01 Spring Boot中使用分页插件PageHelper