不同类型Shell的介绍与使用
立即解锁
发布时间: 2025-09-09 01:53:50 阅读量: 7 订阅数: 22 AIGC 


Linux命令行进阶之旅
### 不同类型 Shell 的介绍与使用
#### 1. 常见 Shell 的发展背景
在 Unix 系统的发展历程中,出现了多种不同的 Shell。最初,Korn shell 是 AT&T 公司的专有软件,直到 2000 年才以开源许可证发布。当 POSIX 对 Unix 系统上使用的 Shell 进行标准化时,它指定了 Korn shell 的一个子集,该子集与早期的 Bourne shell 基本兼容。因此,大多数 Bourne 类型的 Shell 现在都符合 POSIX 标准,但也包含了各种扩展。
部分由于 Korn shell 的专有许可,GNU 项目开发了 bash,它包含了许多 Korn shell 的特性。bash 的第一个版本由 Brian Fox 于 1989 年编写,如今由 Chet Ramey 维护。bash 是大多数 Linux 发行版的默认 Shell,也是 macOS 的默认 Shell,但由于苹果对保密性和封闭性的执着,他们拒绝将 bash 更新到版本 4,因为 GNU GPLv3 中的条款。
自 bash 开发以来,Z shell(zsh)逐渐在 Linux 和 macOS 用户中流行起来。zsh 有时被描述为“Shell 中的 Emacs”,因为它具有大量的特性,为交互式使用添加了许多功能。
#### 2. 现代 Linux 系统中的 Shell 选择
现代 Linux 用户有多种 Shell 程序可供选择,其中 bash 是最受欢迎的,因为它是大多数 Linux 发行版的默认 Shell。不过,从其他 Unix 或类 Unix 系统迁移过来的用户可能更习惯使用其他 Shell。此外,还存在可移植性的问题。如果脚本需要在多个类 Unix 系统上运行,则必须注意以下两点:
1. 确保所有系统都运行相同的 Shell 程序。
2. 编写符合 POSIX 标准的脚本,因为大多数现代 Bourne shell 派生版本都符合 POSIX 标准。
#### 3. 参考脚本示例
为了比较各种 Shell 方言,以下是一个 bash 脚本示例:
```bash
#!/bin/bash
# longest-word : find longest string in a file
for i; do
if [[ -r "$i" ]]; then
max_word=
max_len=0
for j in $(strings "$i"); do
len=${#j}
if (( len > max_len )); then
max_len=$len
max_word=$j
fi
done
echo "$i: '$max_word' ($max_len characters)"
fi
done
```
#### 4. 不同类型 Shell 介绍
##### 4.1 dash - Debian Almquist Shell
dash 是 Debian 对 Almquist shell(ash)的改编,ash 最初由 Kenneth Almquist 在 20 世纪 80 年代编写。ash 是几种 BSD 版本的 Unix 的默认 Shell。dash 和它的祖先 ash 一样,具有体积小、速度快的优点,但它牺牲了一些交互式使用的便利性,如命令历史记录和编辑功能。它还缺少一些内置命令,而是依赖外部程序。它主要用于执行 Shell 脚本,特别是在系统启动期间。在 Debian 和相关发行版(如 Ubuntu)中,dash 被链接到 /bin/sh,用于运行系统初始化脚本。
以下是一个 dash 脚本示例:
```bash
#!/bin/dash
# longest-word.dash : find longest string in a file
for i; do
if [ -r "$i" ]; then
max_word=
max_len=0
for j in $(strings "$i"); do
len=${#j}
if [ $len -gt $max_len ]; then
max_len=$len
max_word=$j
fi
done
echo "$i: '$max_word' ($max_len characters)"
fi
done
```
dash 脚本与 bash 参考脚本基本相同,但也有一些差异。例如,dash 不支持条件测试的 ‘[[’ 语法,它使用较旧的 Bourne shell 语法。POSIX 规范也缺少 ((expression)) 用于算术扩展的语法,也不支持大括号扩展。不过,dash 和 POSIX 规范支持 $(cmd) 用于命令替换的语法,以及较旧的 `cmd` 语法。
##### 4.2 tcsh - TENEX C Shell
tcsh 程序由 Ken Greer 在 20 世纪 80 年代初开发,作为原始 csh 程序的增强替代品。TENEX 这个名字来自同名的操作系统,它对 tcsh 的交互式功能设计产生了影响。与 csh 相比,tcsh 增加了额外的命令历史记录功能、Emacs 和 vi 风格的命令行编辑、拼写纠正等交互式使用的改进。苹果早期版本的 OS X 使用 tcsh 作为默认 Shell,它仍然是几个 BSD 发行版的默认根 Shell。
以下是一个 tcsh 脚本示例:
```tcsh
#!/usr/bin/tcsh
# longest-word.tcsh : find longest string in a file
foreach i ($argv)
set max_word=""
set max_len=0
foreach j (`strings $i`)
set len=$%j
if ($len > $max_len) then
set max_word=$j
set max_len=$len
endif
end
echo "$1 : $max_word ($max_len characters)"
end
```
我们可以看到,tcsh 脚本与 Bourne 风格的语法有很多不同。在 C shell 中,大多数流程控制语句都不同。例如,外层循环以 foreach 语句开始,使用 $argv 中的后续值递增变量 i。argv 来自 C 编程语言,指的是包含命令行参数列表的数组。
虽然这个简单的脚本可以工作,但当事情变得更复杂时,tcsh 的能力就有限了。它有两个主要弱点:
1. 不支持用户定义的函数。作为一种解决方法,可以从主脚本中调用单独的脚本来执行各个函数。
2. 许多使用 POSIX shell 可以轻松完成的复杂结构,如:
```bash
{ if [[ "$a" ]]; then
grep "string1"
else
grep "string2"
fi
} < file.txt
```
在 tcsh 中是不可能实现的,因为 C shell 解析器无法处理带有流程控制语句的重定向。解析器也使引号处理变得非常麻烦。
##### 4.3 ksh - Korn Shell
Korn shell 有几种不同的版本,基本上分为 ksh88 和 ksh93 两组,反映了它们的发布年份。有一个公共领域的 ksh88 版本称为 pdksh,以及 ksh88 和 ksh93 的更官方版本。这三个版本都可用于 Linux。对于大多数用户来说,ksh93 是首选版本,因为它是大多数现代商业 Unix 系统上使用的版本。在安装过程中,它通常被符号链接为 ksh。
以下是一个 ksh 脚本示例:
```ksh
#!/usr/bin/ksh
# longest-word.ksh : find longest string in a file
for i; do
if [[ -r "$i" ]]; then
max_word=
max_len=0
for j in $(strings "$i"); do
len=${#j}
if (( len > max_len )); then
max_len=$len
max_word=$j
fi
done
print "$i: '$max_word' ($max_len characters)"
fi
done
```
从这个示例可以看出,ksh 语法与 bash 非常接近。一个明显的区别是使用
0
0
复制全文
相关推荐









