什么是shell
Shell是操作系统的用户界面,负责接收和解释用户的命令,并将这些命令转化为操作系统内部能够理解的指令,然后执行相应的操作。Shell还允许用户编写脚本,以自动化和批处理任务,从而提高效率。在Linux系统中,有多种不同的Shell可供选择,如Bash、Zsh、Korn Shell等,用户可以根据需要选择最适合他们的Shell来管理和控制系统。这种用户与操作系统之间的交互方式使得Linux系统非常灵活和强大,因为它允许用户以不同的方式自定义和操作系统进行交互。
shell的种类
Linux系统提供多种不同的Shell以供选择。在Linux系统中,默认的Shell是Bourne Again Shell(bash)。:
linux常用的三种shell:
Linux中的shell有多种类型,其中最常用的三种是bourne shell(sh)、c shell(csh)、korn shell(ksh)。
Bourne shell
Bourne shell 是一个交换式的命令解释器和命令编程语言。
Bourne shell曾作为管理系统的常用工具,是UNIX操作系统的标准shell。大部份的系统管理命令文件,例如 rc start、stop 与shutdown 都是Bourne shell 的命令档,且在单一使用者模式(single user mode)下以 root 签入时它常被系统管理者使用。Bourne shell因其简洁高效而闻名,它是由AT&T开发的。 Bourne shell 提示符号的默认值是 $。
c shell
c shell是一种比 Bourne Shell更适合的变种 Shell,使用的是“类C”语法,csh是具有C语言风格的一种shell,其内部命令有52个,较为庞大。
C shell 是柏克莱大学(Berkeley)所开发的,且加入了一些新特性,如命令列历程(history)、别名(alias)、内建算术、档名完成(filename completion)、和工作控制(job control)。对于常在交谈模式下执行 shell 的使用者而言,他们较喜爱使用 C shell;但对于系统管理者而言,则较偏好以 Bourne shell 来做命令档,因为 Bourne shell 命令档比 C shell 命令档来的简单及快速。C shell 提示符号的默认值是 %。
korn shell
korn shell是一个 Unix shell 。在20世纪80年代早期,David Korn在贝尔实验室编写了它。它完全向上兼容 Bourne shell 并包含了 C shell 的很多特性,例如贝尔实验室用户需要的命令编辑。
Korn shell 是Bourne shell 的超集(superset),由 AT&T 的 David Korn 所开发。它增加了一些特色,比 C shell 更为先进。Korn shell 的特色包括了可编辑的历程、别名、函式、正规表达式万用字符(regular expression wildcard)、内建算术、工作控制(job control)、共作处理(coprocessing)、和特殊的除错功能。Bourne shell 几乎和 Korn shell 完全向上兼容(upward compatible),所以在 Bourne shell 下开发的程序仍能在 Korn shell 上执行。Korn shell 提示符号的默认值也是 $。在 Linux 系统使用的 Korn shell 叫做 pdksh,它是指 Public Domain Korn Shell。
在日常使用中,大多数Linux用户会使用Bash,因为它在Linux系统中普遍存在,具有广泛的支持和资源。然而,了解其他Shell也可以为特定的任务和需求提供更多选择。根据具体情况,用户可以切换Shell来执行不同的任务,或者编写特定于Shell的脚本来实现自定义功能。
if else语句
在Linux中,`if`语句是用于条件判断和逻辑控制的关键部分。以下是`if`语句的基本语法,包括`if`、`if else`和`if elif else`的示例:
基本的if语法
语法形式:
if [ condition ]; then
# 如果条件为真,则执行以下代码块
# 可以包含一个或多个命令
fi
示例:
if [ -f file.txt ];
thenecho "file.txt 存在。"
fi
if else语法
if [ condition ]; then
# 如果条件为真,则执行以下代码块
else
# 如果条件为假,则执行以下代码块
fi
示例:
if [ -f file.txt ];
thenecho "file.txt 存在。"
elseecho "file.txt 不存在。"
fi
if elif else语法
if [ condition1 ]; then
# 如果条件1为真,则执行以下代码块
elif [ condition2 ]; then
# 如果条件2为真,则执行以下代码块
else
# 如果前面的条件都为假,则执行以下代码块
fi
示例:
if [ -d directory ]; thenecho "directory 存在且是一个目录。"
elif [ -f file ]; thenecho "file 存在且是一个文件。"
elseecho "directory 和 file 都不存在。"
fi
在这些语法中,`[ condition ]`用于表示条件测试,根据条件的真假执行不同的代码块。您可以根据具体的需求嵌套`if`语句来进行更复杂的逻辑控制。
注意:
(())是一种数学计算命令,它除了可以进行最基本的加减乘除运算,还可以进行大于、小于、等于等关系运算,以及与、或、非逻辑运算。当 a 和 b 相等时,(( a==b ))判断条件成立,进入 if,执行 then 后边的 echo 语句。更多关于(())的介绍,可参考Linux Shell - 运算符。
if条件判断句的退出状态
在Linux中,命令的退出状态是一个整数值,通常被称为退出码(Exit Code)或退出状态码(Exit Status)。这个退出状态用于表示命令的执行结果,通常遵循以下规则:
- 退出状态为0表示成功执行。
- 非零退出状态表示命令执行失败或出现问题。
通常,非零退出状态可以用来指示命令的特定错误类型或问题。不同的命令可能使用不同的非零退出状态来表示不同的错误条件。例如,像您提到的`diff`命令,返回0表示没有差异,返回1表示找到差异,返回2表示出现无效文件名等。
在Shell脚本中,您可以使用特殊变量`$?`来获取上一个命令的退出状态。以下是一个示例:
```bash
#!/bin/bashls /nonexistent_directory # 运行一个不存在的命令
if [ $? -eq 0 ]; thenecho "Command executed successfully"
elseecho "Command failed with exit status $?"
fi
```
在上面的示例中,`ls /nonexistent_directory`命令会失败,因为指定的目录不存在。`$?`用于获取上一个命令的退出状态,然后通过条件判断来输出相应的消息。通过检查命令的退出状态,Shell脚本可以根据命令的执行结果采取不同的操作,使脚本更具弹性和鲁棒性。
退出状态和逻辑运算符的组合
Shell的if
语句可以使用逻辑运算符来组合多个命令的退出状态,以便进行多个条件的判断。常见的逻辑运算符有&&
(逻辑与)、||
(逻辑或)和!
(逻辑非)。以下是一些示例:
运算符 | 使用格式 | 说明 |
---|---|---|
&& 或 -a | 条件1 && 条件2 | 逻辑与运算符,当 条件1 和 条件2 同时成立时,整个表达式才成立。 如果检测到条件1 的退出状态为 0,就不会再检测 条件2 了,因为不管条件2 的退出状态是什么,整个表达式必然都是不成立的,检测了也是多此一举。 |
|| 或 -o | 条件1 || 条件2 | 逻辑或运算符,条件1 和 条件2 两个表达式中只要有一个成立,整个表达式就成立。 如果检测到 条件1 的退出状态为 1,就不会再检测 条件2 了,因为不管 条件2 的退出状态是什么,整个表达式必然都是成立的,检测了也是多此一举。 |
! | !条件 | 逻辑非运算符,相当于”取反“的效果。如果 条件成立,那么整个表达式就不成立;如果 条件 不成立,那么整个表达式就成立。 |
具体代码:
if [ -f file1 ] && [ -f file2 ];
thenecho "Both file1 and file2 exist."
fiif [ -d directory1 ] || [ -d directory2 ];
thenecho "At least one of directory1 or directory2 exists."
fiif ! [ -e file1 ];
thenecho "file1 does not exist."
fi
while语句
`while`语句在Linux中用于循环执行一系列命令,可以用来创建不定次数的循环。以下是`while`语句的基本语法,包括一个简单的示例:
while [ condition ]
do
# 在条件为真时执行以下命令
done注意:condition`是一个测试条件,当条件为真时,`do`和`done`之间的命令会被执行。当`condition`的值为假时,循环结束,脚本继续执行后续的命令。
#!/bin/bashcount=0while [ $count -lt 5 ]
doecho "Hello, World"count=$((count + 1))
done
使用`break`语句来在循环中提前退出循环,或者使用其他条件来控制循环的终止条件,以满足不同的需求。
until语句
until
语句是Shell中的另一种循环控制结构,与while
循环相反,它会一直循环直到条件为真。当条件为假(返回值为1,代表false)时,until
循环会继续执行,而当条件为真时,循环终止。
以下是until
语句的基本语法和示例:
until [ condition ]
do
# 在条件为假时执行以下命令
done
示例:指定输出多少次hello world
#!/bin/bashcount=0until [ $count -ge 5 ]
doecho "Hello, World"count=$((count + 1))
done
for语句
与其他编程语言类似,Shell同样支持for循环,允许您=在指定范围内或一组项目上进行迭代。
循环方式一:在指定的一组项目上进行迭代
语法形式:
for var in item1 item2 ... itemN
do
# 在每个项目上执行命令
done
注意:var
是循环变量,item1 item2 ... itemN
是循环的范围。
示例:输出5次hello world
#!/bin/bashfor i in 1 2 3 4 5
doecho "Hello, World"
done
循环方式二:在指定的整数范围内进行迭代
语法形式:
for ((start; end; step))
do
# 在指定范围内执行命令
done
注意:start
表示循环范围的起始值,必须为整数;end
表示循环范围的结束值,必须为整数。
示例:循环1到5并打印
#!/bin/bashfor ((i=1; i<=5; i++))
doecho $i
done
循环方式三:在不同的用法中,可以使用通配符来表示一组项目
无限循环语法:
for var in {item1,item2,...,itemN}
do
# 在每个项目上执行命令
done
示例:打印5次hello world
#!/bin/bashfor i in {1,2,3,4,5}
doecho "Hello, World"
done
select语句
select
语句是Shell的一种特殊循环,用于创建交互式菜单,用户可以从菜单中选择一个编号并执行相应的操作,增强交互性。select
语句通常与case
语句一起使用,以根据用户的选择执行不同的命令。 select in 是 Shell 独有的一种循环,非常适合终端(Terminal)这样的交互场景,而其他语言则没有。以下是select
语句的基本语法和示例。
注意:select 是无限循环(死循环),输入空值,或者输入的值无效都不会结束循环,只有遇到 break 语句,或者按下 Ctrl+D
组合键才能结束循环。 执行命令过程中,终端会输出 #?
代表可以输入选择的菜单编号。
基础语法:
select var in item1 item2 ... itemN
do
# 显示菜单并等待用户选择
# 用户选择后,执行与选择相关的命令
done
注:
var
是用户选择的编号。item1
、item2
等是菜单中的选项。
示例1:
#!/bin/bashselect option in "Option 1" "Option 2" "Option 3" "Quit"
docase $option in"Option 1")echo "You chose Option 1";;"Option 2")echo "You chose Option 2";;"Option 3")echo "You chose Option 3";;"Quit")break;;*)echo "Invalid option";;esac
done
case语句
Shell case语句为多选择语句。可以用case语句匹配一个值与一个模式,如果匹配成功,执行相匹配的命令;当分支较多,并且判断条件比较简单时,使用 case in 语句就比较方便了。
每一匹配模式必须以右括号结束。取值可以为变量或常数。匹配发现取值符合某一模式后,其间所有命令开始执行直至;;
(类似break)。取值将检测匹配的每一个模式,一旦模式匹配,则执行完匹配模式相应命令后不再继续其他模式。如果无一匹配模式,使用星号 * 捕获该值,再执行后面的命令。 case
、in
和 esac
都是 Shell 关键字, esac就是case的反写在这里代表结束case。
语法形式:
case value in
pattern1)
# 当value匹配pattern1时执行这里的命令
;;
pattern2)
# 当value匹配pattern2时执行这里的命令
;;
pattern3)
# 当value匹配pattern3时执行这里的命令
;;
*)
# 当value与上述模式都不匹配时执行这里的命令
;;
esac注意:
value是要匹配的值。
pattern1、pattern2、pattern3 等是不同的模式,可以是数字、字符串,也可以包括通配符。
;; 表示模式匹配后,执行完命令后结束case语句。
匹配模式:可以是一个数字、一个字符串,甚至是一个简单正则表达式。简单正则表达式支持如下通配符:
格式 | 说明 |
---|---|
* | 表示任意字符串。 |
[abc] | 表示 a、b、c 三个字符中的任意一个。比如,[15ZH] 表示 1、5、Z、H 四个字符中的任意一个。 |
[m-n] | 表示从 m 到 n 的任意一个字符。比如,[0-9] 表示任意一个数字,[0-9a-zA-Z] 表示字母或数字。 |
| | 表示多重选择,类似逻辑运算中的或运算。比如,abc | xyz 表示匹配字符串 “abc” 或者 “xyz”。 |
演示:
#!/bin/bashfruit="apple"case $fruit in"apple")echo "It's an apple.";;"banana")echo "It's a banana.";;"cherry")echo "It's a cherry.";;*)echo "It's something else.";;
esac