shell基本语法
本节介绍一些常见的shell脚本语法
一、常见运算符
数值运算符:
+
:加法-
:减法*
:乘法/
:除法%
:取余
字符串运算符:
=
:字符串相等!=
:字符串不相等-z
:字符串为空-n
:字符串非空str1 + str2
:拼接字符串
数值比较运算符:
-eq
:等于 (equal to)-ne
:不等于 (not equal to)-lt
:小于 (less than)-le
:小于等于 (less than or equal to)-gt
:大于 (greater than)-ge
:大于等于 (greater than or equal to)
二、循环语句
while循环
以下是
while
循环的基本语法:while condition do # 代码块 done
其中,
condition
是一个需要评估的条件表达式,可以是关系表达式、逻辑表达式或函数返回值等。只有当 condition
为真时,循环中的代码块才会被执行。代码块由 do
和 done
来标记。下面是一个简单的示例,演示了
while
循环的用法:count=0 while [ $count -lt 5 ] do echo "Count: $count" count=$((count+1)) # 自增 count 变量 done
以上代码会输出从 0 到 4 的计数值。
while
循环首先检查条件 $count -lt 5
是否为真,如果为真,则会执行循环中的代码块。在每次迭代时,会输出当前的计数值并将 count 变量自增。当 count 达到 5 时,条件为假,循环结束。for循环
以下是
for
循环的基本语法:for variable in list do # 代码块 done
其中,
variable
是一个用于保存当前迭代元素的变量名,list
是需要迭代的元素列表或范围。list
可以是用空格分隔的多个值,也可以是利用通配符来匹配多个文件名。另外,还可以使用 {start..end}
表达式来生成一个范围内的数字序列。下面为两个简单示例:
for num in {1..5} do echo "Number: $num" done
以上代码会迭代从 1 到 5 的数字序列,并输出每个数字。 需要注意的是,在 for 循环中,变量的赋值使用的是in关键字,而不是等号(=)。 for 循环还支持其他控制语句,例如 break 和 continue,用于提前终止循环或跳过当前迭代
#/bin/bash.sh for times in $(seq 1 10) do echo "$times" done
表示输出1-10
三、判断语句
if语句
if
结构用于基于给定条件进行条件判断,并根据判断结果来决定执行哪个代码块。它可以包含多个条件分支,每个分支由 if
、then
、elif
(可选)和 else
(可选)组成。# 单分支语句 ---比较大小 if (条件表达式);then 语句1 fi # 双分支if 语句 if (表达式) 语句1 else 语句2 fi # 多支条件语句 if (表达式) 语句1 elif 语句2 elif 语句2 fi
下面为一简单举例:
score=85 if [ $score -ge 90 ]; then echo "优秀" elif [ $score -ge 80 ]; then echo "良好" else echo "及格" fi
以上代码根据变量 score 的值进行条件判断,并输出相应的成绩等级。
case语句
case
结构用于基于不同模式匹配执行对应的代码块。它类似于多个 if-else 分支判断,但更适用于比较复杂的模式匹配需求。以下是
case
结构的基本语法:case expression in pattern1) # 代码块1 ;; pattern2) # 代码块2 ;; pattern3) # 代码块3 ;; *) # 默认代码块 ;; esac
其中,
expression
是要进行匹配的表达式,pattern1
、pattern2
、pattern3
是不同的模式,*
是默认模式。例如:
fruit="apple" case $fruit in "apple") echo "这是一个苹果" ;; "orange" | "lemon") echo "这是一个橘子或柠檬" ;; *) echo "未知水果" ;; esac
以上代码根据变量
fruit
的值进行模式匹配,并输出相应的提示信息。注意,在
case
结构中,每个模式末尾需要使用双分号 ;;
表示结束当前分支的代码块。四、常见命令
let命令
let
是一种用于执行算术运算的内置命令。它可以用于执行基本的数值计算,并将结果赋给变量以下是一些示例说明
let
命令的使用:let a=5+3 # 将 5 + 3 的结果赋给变量 a echo $a # 输出结果为 8 let "b = 2 * (10 - 4)" # 将 2 * (10 - 4) 的结果赋给变量 b echo $b # 输出结果为 12 c=7 let c++ # 对变量 c 进行自增操作,等价于 c=c+1 echo $c # 输出结果为 8 let "d = (5 > 3) && (2 < 4)" # 执行逻辑运算,并将结果赋给变量 d echo $d # 输出结果为 1(真)
需要注意的是,
let
命令执行的是整数运算,如果涉及到浮点数运算,let
命令会进行截断取整。[[ ]]、[]
单括号
[ ]
: 单括号 [ ]
是最基本的条件测试结构,在早期版本的 Bash 中被广泛使用。它可以用于测试多种条件,包括字符串比较、数值比较和文件属性等。使用单括号时,通常需要在变量周围添加引号,以避免一些特殊字符的问题。并且,需要注意使用不同的比较符号(例如
=
、!=
、-eq
)来进行条件判断。例如:
shellCopy Code if [ "$var" = "abc" -a "$num" -gt 10 ]; then echo "条件满足" else echo "条件不满足" fi
双括号
[[ ]]
: 双括号 [[ ]]
是 Bash shell 的扩展条件测试结构,提供了更多的功能和便利性。它支持字符串模式匹配、正则表达式匹配、逻辑操作符的嵌套等。与单括号不同,双括号内的变量可以不使用引号进行包裹,这意味着在条件测试中可以直接使用变量而不必担心特殊字符的影响。
例如:
shellCopy Code if [[ $var == "abc" && $num -gt 10 ]]; then echo "条件满足" else echo "条件不满足" fi
总结一下,单括号
[ ]
是最基本的条件测试结构,适用于基本的条件判断;而双括号 [[ ]]
是扩展的条件测试结构,提供了更多的功能和便利性,可以进行更灵活的条件判断。在使用时,建议优先使用双括号 [[ ]]
,除非必须与其他 shell 兼容或需要特定的行为时,才使用单括号 [ ]
。()、(())
()
: ()
是用于创建子shell(subshell)的一种方式,在子shell 中执行相关的命令。子shell 是一个独立的进程,具有自己的环境变量和变量作用域。使用
()
可以将一组命令括在括号内,并作为一个整体进行处理。这样可以在子shell 中执行这组命令,并在子shell 完成后返回到原来的shell 中。例如:
shellCopy Code #!/bin/bash count=0 ( count=$((count+1)) echo "This is in the subshell. Count: $count" ) echo "Back to the main shell. Count: $count"
以上代码创建了一个子shell,在子shell 中对
count
进行自增操作并输出结果。然后,回到主shell 输出原始的 count
值。(())
: (())
是用于执行算术运算和逻辑运算的结构,在其中可以使用变量和运算符进行数值计算和逻辑判断。(())
结构会对其中的表达式进行求值,并返回计算结果。它支持基本的算术运算符、逻辑运算符和位运算符。例如:
a=5 b=3 result=$((a + b)) echo "The result is: $result"
以上代码使用
(())
结构进行算术运算,计算变量 a
和 b
的和,并将结果赋给 result
变量。然后输出计算结果。需要注意的是,在
(())
结构中不需要使用美元符号 $
来引用变量,直接使用变量名即可。综上所述,
()
是用于创建子shell,可以在其中执行一组命令;(())
是用于执行算术运算和逻辑运算的结构,用于进行数值计算和逻辑判断。read -p
read -p
是一个用于读取用户输入的命令。-p
参数用于在读取输入之前显示提示信息。示例:
#!/bin/bash read -p "请输入您的名字: " name echo "您好,$name!"
上述示例中,使用
read -p
提示用户输入名字,并将用户输入的值存储在 name
变量中。然后通过 echo
命令输出欢迎消息,包含用户输入的名字。运行脚本时,用户将看到一个提示,等待输入名字。用户输入名字后,脚本将继续执行并输出欢迎消息。
-d
-d
是用作条件测试命令 [ ]
或 test
的选项之一,用于检查给定路径是否为一个存在的目录以下是一个示例,展示了如何使用
-d
来检查目录是否存在:path="/data/rivers" if [ -d "$path" ]; then echo "目录存在" else echo "目录不存在" fi
在上述示例中,如果
/data/rivers
目录存在,则输出 "目录存在";否则输出 "目录不存在"。需要注意的是,在条件测试中,
path
需要使用引号引起来,以避免路径中存在空格等特殊字符时出现问题。-a
在条件测试中,使用
-a
可以将多个条件连接起来,并在所有条件都为真时返回真值。-a
实际上是逻辑 AND 运算符的一种替代方式。但需要注意的是,使用
-a
存在一些问题和不推荐的情况。根据 POSIX 标准,应使用双中括号 [[ ]]
来进行条件测试,且不使用 -a
选项。另外,还可以使用双和号 &&
来代替 -a
,更加简洁和易读。因此,建议优先使用 [[ ]]
和 &&
来执行逻辑 AND 操作,而非使用 -a
。以下是一个示例,展示了
-a
的用法,说明了如何在条件测试中使用 -a
执行逻辑 AND 操作:if [ "$var1" -gt 10 -a "$var2" == "abc" ]; then echo "条件满足" else echo "条件不满足" fi
在上述示例中,如果变量
var1
大于 10 并且变量 var2
的值等于 "abc",则条件被认为是真,输出 "条件满足"。否则输出 "条件不满足"。%F %T
通常用于格式化日期和时间的字符串输出。
%F
是用于格式化日期的占位符,它代表完整的日期,包括年份、月份和日期,使用格式为YYYY-MM-DD
。%T
是用于格式化时间的占位符,它代表完整的时间,包括小时、分钟和秒钟,使用 24 小时制,格式为HH:MM:SS
。
这些占位符通常用于命令如
date
等,用于获取当前日期和时间,并进行格式化输出。以下是一个示例,演示了如何使用
%F
和 %T
进行日期和时间的格式化输出:current_date=$(date +'%F') current_time=$(date +'%T') echo "Today's date is: $current_date" echo "Current time is: $current_time"
以上代码会获取当前的日期和时间,并将其格式化为
%F
和 %T
所示的格式进行输出。set -x
set -x
是一个用于开启调试模式的选项。当执行这个命令后,Shell 会将脚本的每一行命令都显示出来,并在命令执行之前先输出该行命令。以下是一个示例,展示了如何使用
set -x
开启调试模式:#!/bin/bash set -x # 以下是脚本的主要逻辑 echo "开始执行脚本" for i in {1..5}; do echo "Loop $i" done echo "脚本执行完毕" set +x # 调试模式已关闭,以下的命令不会显示 echo "调试模式已关闭"
在上述示例中,
set -x
命令在脚本的开头设置了调试模式。当脚本执行时,每个命令都会被显示出来,以及其执行结果。set +x
命令用于关闭调试模式,在该命令之后的命令将不再显示。通过开启调试模式,可以更直观地看到脚本执行过程中每一行命令的执行情况,帮助进行调试或排错。
$1 $2 ...
$1
和 $2
是命令行参数的占位符,用于引用在脚本执行时传递给它的参数。$1
代表第一个命令行参数。$2
代表第二个命令行参数。
在Shell脚本中,当你执行脚本并传递参数时,可以通过这些变量来引用和访问这些参数。
以下是一个示例,演示了如何在Shell脚本中使用
$1
和 $2
:#!/bin/bash echo "第一个参数: $1" echo "第二个参数: $2"
假设脚本名为
script.sh
,你可以通过以下方式执行脚本并传递两个参数:./script.sh value1 value2
脚本会分别输出传递的两个参数的值。在此示例中,
$1
的值将是 "value1",$2
的值将是 "value2"。