Shell语言

2024/03/03 Shell 共 4900 字,约 15 分钟

Shell语言

定义

  • Shell:计算机壳层,区别于“计算机内核”。指“为使⽤者提供操作界⾯”的软件,⽤于接收⽤⼾命

令,调⽤相应的应⽤程序。

  • Shell脚本:为shell设计的⼀种脚本语⾔,⽅便进⾏复杂逻辑的shell命令的调⽤。

语法

hello world

echo 'hello world'
echo "hello world"
var="hello world"
echo $var
  • 赋值号=左右不能有空格

单引号与双引号的区别

var="world"
echo "hello $var"
echo 'hello $var'
  • 单引号原样输出字符串,双引号会解析变量

将命令的结果赋值给变量

  • 反引号 ``
  • $()
var=`cat hhh.txt`
var=$(cat hhh.txt)

只读变量

  • readonly 常量
#!/bin/bash
const="const"
readonly const
const="var"
  • 不能修改常量

删除变量

var="hello"
echo $var
>>hello
unset var
echo $var
>>

变量作用域

全局变量

  • 可以在当前shell会话中使⽤
#!/bin/bash
function func(){
	var="hello"
}
func
echo $var

变量var在函数外仍能读取

局部变量

  • 只能在函数内部使⽤
#!/bin/bash
function func(){
	local var="hello"
}
func
echo $var

环境变量

var="hello"
export var
  • export的变量仅在当前shell和子shell中可见,需要在任何shell中可见需要修改环境变量参数

位置参数

shell脚本使⽤$n的形式接收调⽤脚本时给脚本传递的参数,这种变量形式叫做位置参数

#!/bin/bash
echo $1 $2 $3
  • shell脚本的函数使用位置参数代替形参实参的功能
#!/bin/bash
function func(){
	echo $1
}
func "123"

shell脚本中的特殊变量

变量含义
$0当前脚本的文件名
$n(n≥1)传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是 $1,第二个参数是 $2。
$#传递给脚本或函数的参数个数。
$*传递给脚本或函数的所有参数。
$@传递给脚本或函数的所有参数。当被双引号” “包含时,$@ 与 $* 稍有不同,我们将在《Shell $*和$@的区别》一节中详细讲解。
$?上个命令的退出状态,或函数的返回值,我们将在《Shell $?》一节中详细讲解。
$$当前 Shell 进程 ID。对于 Shell 脚本,就是这些脚本所在的进程 ID。

$*和$@的区别

当 $* 和 $@ 不被双引号” “包围时,它们之间没有任何区别,都是将接收到的每个参数看做⼀份数据,彼此之间以空格来分隔。

但是当它们被双引号” “包含时,就会有区别了:

  • ”$*“会将所有的参数从整体上看做⼀份数据,⽽不是把每个参数都看做⼀份数据。
  • ”$@”仍然将每个参数都看作⼀份数据,彼此之间是独⽴的。
#!/bin/bash
echo 'print each param from $*'
for var in "$*"
do
	echo "$var"
done
echo 'print each param from $@'
for var in "$@"
do
	echo "$var"
done

字符串

获取字符串长度

  • ${#string_name}
var=hello
echo ${#var}

字符串截取

格式说明
${string: start :length}从 string 字符串的左边第 start 个字符开始,向右截取 length 个字符。0起始
${string: start}从 string 字符串的左边第 start 个字符开始截取,直到最后。0起始
${string: 0-start :length}从 string 字符串的右边第 start 个字符开始,向右截取 length 个字符。1起始
${string: 0-start}从 string 字符串的右边第 start 个字符开始截取,直到最后。1起始
${string#*chars}从 string 字符串第一次出现 *chars 的位置开始,截取 *chars 右边的所有字符。星号是通配符,表示任意长度字符串
${string##*chars}从 string 字符串最后一次出现 *chars 的位置开始,截取 *chars 右边的所有字符。
${string%*chars}从 string 字符串第一次出现 *chars 的位置开始,截取 *chars 左边的所有字符。
${string%%*chars}从 string 字符串最后一次出现 *chars 的位置开始,截取 *chars 左边的所有字符。

数组

定义

arr=(20 56 "shell")
nums[6]=88
ages=([3]=24 [5]=19 [10]=12)

使用数组

  • 获取数组元素
${array_name[index]}
  • 获取全部元素
${nums[*]}
${nums[@]}
  • 获取数组长度
${#nums[*]}
${#nums[@]}
  • 拼接合并数组
array_new=(${array1[@]} ${array2[@]})
array_new=(${array1[*]} ${array2[*]})
  • 删除数组/数组元素
unset array_name[index]
unset array_name

循环

  • 迭代器形式
#!/bin/bash
arr=(1 2 3 4 5 6 7 8 9)
for item in ${arr[@]}
do
	echo $item
done
  • while
#!/bin/bash
i=0
sum=0
while((i < 10))
do
	((sum=sum+i))
	((i++))
done
echo $sum
#!/bin/bash
index=0
arr=(1 2 3 4 5 6 7 8 9)
while ((index < ${#arr[*]}))
do
	echo ${arr[index]}
	((index++))
done
  • until
#!/bin/bash
i=0
sum=0
until ((i>=10))
do
	((sum=sum+i))
	((i=i+1))
done
echo $sum

内建命令

  • 由bash自身提供的命令,而不是文件系统中的某个可执行文件
  • 类似于关键字保留字
       
bash:.[aliasbgbind
breakbuiltincdcommandcompgencompletecontinue
declaredirsdisownechoenableevalreturn
execexitexportfcfggetoptsset
hashhelphistoryjobskillletshift
locallogoutpopdprintfpushdpwdshopt
readreadonlysourcesuspendtesttimestrap
typetypesetulimitumaskunaliasunsetwait

数学计算

运算操作符/运算命令说明
(( ))用于整数运算,效率很高,推荐使用
let用于整数运算,和 (()) 类似。
[$]用于整数运算,不如 (()) 灵活。
expr可用于整数运算,也可以处理字符串。比较麻烦,需要注意各种细节,不推荐使用。
bcLinux下的一个计算器程序,可以处理整数和小数。Shell 本身只支持整数运算,想计算小数就得使用 bc 这个外部的计算器。
declare -i将变量定义为整数,然后再进行数学运算时就不会被当做字符串了。功能有限,仅支持最基本的数学运算(加减乘除和取余),不支持逻辑运算、自增自减等,所以在实际开发中很少使用。

if语句

#!/bin/bash
read a
read b
if (($a == $b))
	then
		echo "a == b"
	else
		echo "a != b"
fi
#!/bin/bash
read a
if (($a == 1)); then
	echo "one"
elif (($a == 2)); then
	echo "two"
elif (($a == 3)); then
	echo "three"
fi

test命令

test expression

简写等同于

[ expression ]
  • 比较符号
1. #!/bin/bash
2. read age
3. if test $age -le 2; then
4.     echo "婴儿"
5. elif test $age -ge 3 && test $age -le 8; then
6.     echo "幼儿"
7. elif [ $age -ge 9 ] && [ $age -le 17 ]; then
8.     echo "少年"
9. elif [ $age -ge 18 ] && [ $age -le 25 ]; then
10.     echo "成年"
11. elif test $age -ge 26 && test $age -le 40; then
12.     echo "青年"
13. elif test $age -ge 41 && [ $age -le 60 ]; then
14.     echo "中年"
15. else
16.     echo "老年"
17. fi

test相关选项

文件类型判断 
选 项作 用
-b filename判断文件是否存在,并且是否为块设备文件。
-c filename判断文件是否存在,并且是否为字符设备文件。
-d filename判断文件是否存在,并且是否为目录文件。
-e filename判断文件是否存在。
-f filename判断文件是否存在,井且是否为普通文件。
-L filename判断文件是否存在,并且是否为符号链接文件。
-p filename判断文件是否存在,并且是否为管道文件。
-s filename判断文件是否存在,并且是否为非空。
-S filename判断该文件是否存在,并且是否为套接字文件。
文件权限判断 
选 项作 用
-r filename判断文件是否存在,并且是否拥有读权限。
-w filename判断文件是否存在,并且是否拥有写权限。
-x filename判断文件是否存在,并且是否拥有执行权限。
-u filename判断文件是否存在,并且是否拥有 SUID 权限。
-g filename判断文件是否存在,并且是否拥有 SGID 权限。
-k filename判断该文件是否存在,并且是否拥有 SBIT 权限。
文件比较 
选 项作 用
filename1 -nt filename2判断 filename1 的修改时间是否比 filename2 的新。
filename -ot filename2判断 filename1 的修改时间是否比 filename2 的旧。
filename1 -ef filename2判断 filename1 是否和 filename2 的 inode 号一致,可以理解为两个文件是否为同一个文件。这个判断用于判断硬链接是很好的方法

与数值比较相关的 test 选项

选 项作 用
num1 -eq num2判断 num1 是否和 num2 相等。
num1 -ne num2判断 num1 是否和 num2 不相等。
num1 -gt num2判断 num1 是否大于 num2 。
num1 -lt num2判断 num1 是否小于 num2。
num1 -ge num2判断 num1 是否大于等于 num2。
num1 -le num2判断 num1 是否小于等于 num2。

与字符串判断相关的 test 选项

选 项作 用
-z str判断字符串 str 是否为空。
-n str判断宇符串 str 是否为非空。
str1 = str2 str1 == str2===是等价的,都用来判断 str1 是否和 str2 相等。
str1 != str2判断 str1 是否和 str2 不相等。
str1 > str2判断 str1 是否大于 str2。\>>的转义字符,这样写是为了防止>被误认为成重定向运算符。
str1 < str2判断 str1 是否小于 str2。同样,\<也是转义字符。

与逻辑运算相关的 test 选项

选 项作 用
expression1 -a expression逻辑与,表达式 expression1 和 expression2 都成立,最终的结果才是成立的。
expression1 -o expression2逻辑或,表达式 expression1 和 expression2 有一个成立,最终的结果就成立。
!expression逻辑非,对 expression 进行取反。

文档信息

Search

    Table of Contents