Debian教程

Debian Shell脚本

Shell脚本是Debian操作系统中常用的一种脚本语言,用于执行系统管理和自动化任务。本教程将介绍Debian Shell脚本的各个方面,包括POSIX shell兼容性、Shell参数、条件语句、循环、环境变量、命令行处理顺序以及用于Shell脚本的应用程序等内容。

一、POSIX shell兼容性

系统中的许多脚本都可以通过任意 POSIX shell来执行。

  • 默认的非交互 POSIX shell "/usr/bin/sh" 是一个指向到 /usr/bin/dash 的符号链接,并被许多系统程序使用。
  • 默认的交互式 POSIX shell 是 /usr/bin/bash。

避免编写具有 bashisms(bash 化)或者 zshisms(zsh 化)语法的 shell 脚本,确保脚本在所有 POSIX shell 之间具有可移植性。你可以使用 checkbashisms(1) 对其进行检查。

典型 bashism 语法列表:

好的:POSIX 应该避免的:bashism
if [ "$foo" = "$bar" ] ; then … if [ "$foo" == "$bar" ] ; then …
diff -u file.c.orig file.c diff -u file.c{.orig,}
mkdir /foobar /foobaz mkdir /foo{bar,baz}
funcname() { … } function funcname() { … }
八进制格式:"\377" 十六进制格式:"\xff"

使用 "echo" 命令的时候需要注意以下几个方面,因为根据内置 shell 和外部命令的不同,它的实现也有差别。

注意:

  • 避免使用除“-n”以外的任何命令行选项;
  • 避免在字符串中使用转义序列,因为根据 shell 不同,计算后的结果也不一样;
  • 尽管“-n”选项并不是 POSIX 语法,但它已被广泛接受;
  • 如果你想要在输出字符串中嵌入转义序列,用 "printf" 命令替代 "echo" 命令。

二、Shell参数

特殊的 shell 参数经常在 shell 脚本里面被用到。

shell 参数列表:

shell 参数
$0 shell 或 shell 脚本的名称
$1 第一个 shell 参数
$9 第 9 个 shell 参数
$# 位置参数数量
"$*" "$1 $2 $3 $4 … "
"$@" "$1" "$2" "$3" "$4" …
$? 最近一次命令的退出状态码
$$ 这个 shell 脚本的 PID
$! 最近开始的后台任务 PID

如下所示是需要记忆的基本的参数展开。

shell 参数展开列表:

参数表达式形式 如果 var 变量已设置那么值为 如果 var 变量没有被设置那么值为
${var:-string} "$var" "string"
${var:+string} "string" "null"
${var:=string} "$var" "string" (并运行 "var=string")
${var:?string} "$var" 在 stderr 中显示 "string" (出错退出)

以上这些操作中 ":" 实际上都是可选的。

  • 有 ":" 等于测试的 var 值是存在且非空;
  • 没有 ":" 等于测试的 var 值只是存在的,可以为空。

重要的 shell 参数替换列表:

参数替换形式 结果
${var%suffix} 删除位于 var 结尾的 suffix 最小匹配模式
${var%%suffix} 删除位于 var 结尾的 suffix 最大匹配模式
${var#prefix} 删除位于 var 开头的 prefix 最小匹配模式
${var##prefix} 删除位于 var 开头的 prefix 最大匹配模式

三、Shell条件语句

每个命令都会返回退出状态,这可以被条件语句使用。

  • 成功:0 ("True");
  • 失败:非 0 ("False")。

注意:

  • "0" 在 shell 条件语句中的意思是 "True",然而 "0" 在 C 条件语句中的含义为 "False";
  • "[" 跟 test 命令是等价的,它评估到 "]" 之间的参数来作为一个条件表达式。

如下所示是需要记忆的基础 条件语法:

  • "command && if_success_run_this_command_too || true"
  • "command || if_not_success_run_this_command_too || true"

如下所示是多行脚本片段:

if [ conditional_expression ]; then
if_success_run_this_command
else
if_not_success_run_this_command
fi

这里末尾的“|| true”是需要的,它可以保证这个 shell 脚本在不小心使用了“-e”选项而被调用时不会在该行意外地退出。

在条件表达式中进行文件比较:

表达式 返回逻辑真所需的条件
-e file file 存在
-d file file 存在并且是一个目录
-f file file 存在并且是一个普通文件
-w file file 存在并且可写
-x file file 存在并且可执行
file1 -nt file2 file1 是否比 file2 新
file1 -ot file2 file1 是否比 file2 旧
file1 -ef file2 file1 和 file2 位于相同的设备上并且有相同的 inode 编号

在条件表达式中进行字符串比较:

表达式 返回逻辑真所需的条件
-z str str 的长度为零
-n str str 的长度不为零
str1 = str2 str1 和 str2 相等
str1 != str2 str1 和 str2 不相等
str1 < str2 str1 排列在 str2 之前(取决于语言环境)
str1 > str2 str1 排列在 str2 之后(取决于语言环境)

算术整数的比较在条件表达式中为 "-eq","-ne","-lt","-le","-gt" 和 "-ge"。

四、shell循环

这里有几种可用于 POSIX shell 的循环形式。

  • "for x in foo1 foo2 … ; do command ; done",该循环会将 "foo1 foo2 …" 赋予变量 "x" 并执行 "command";
  • "while condition ; do command ; done",当 "condition" 为真时,会重复执行 "command";
  • "until condition ; do command ; done",当 "condition" 为假时,会重复执行 "command";
  • "break" 可以用来退出循环;
  • "continue" 可以用来重新开始下一次循环。

注意:C 语言中的数值迭代可以用 seq(1) 实现来生成 "foo1 foo2 ...";

五、Shell环境变量

普通的 shell 命令行提示下的一些常见的环境变量,可能在你的脚本的执行环境中不存在。

  • 对于 "$USER", 使用 "$(id -un)";
  • 对于 "$UID", 使用 "$(id -u)";
  • 对于 "$HOME",使用"$(getent passwd "$(id -u)"|cut -d ":" -f 6)" 。

六、shell命令行处理顺序

shell 大致以下列的顺序来处理一个脚本。

1、shell 读取一行。

2、如果该行包含有"…" 或 '…',shell 对该行各部分进行分组作为 一个标识(one token) (译注:one token 是指 shell 识别的一个结构单元).

3、shell 通过下列方式将行中的其它部分分隔进 标识(tokens)。

  • 空白字符:空格 tab 换行符;
  • 元字符: < > | ; & ( )。

4、shell 会检查每一个不位于 "…" 或 '...' 的 token 中的 保留字 来调整它的行为。

  • 保留字:if then elif else fi for in while unless do done case esac

5、shell 展开不位于 "…" 或 '...' 中的 别名。

6、shell 展开不位于 "…" 或 '...' 中的 波浪线。

  • "~" → 当前用户的家目录;
  • "~user" → user 的家目录。

7、shell 将不位于 '...' 中的 变量 展开为它的值。

  • 变量:"$PARAMETER" 或 "${PARAMETER}"

8、shell 展开不位于 '...' 中的 命令替换。

  • "$( command )" → "command" 的输出;
  • "` command `" → "command" 的输出。

9、shell 将不位于 "…" 或 '...' 中的 glob 路径 展开为匹配的文件名。

  • * → 任何字符;
  • ? → 一个字符;
  • […] → 任何位于 "…" 中的字符。

10、shell 从下列几方面查找 命令 并执行。

  • 函数定义;
  • 内建命令;
  • “$PATH” 中的可执行文件。

shell 前往下一行,并按照这个顺序从头再次进行处理。

双引号中的单引号是没有效果的。在 shell 中执行 “set -x” 或使用 “-x” 选项启动 shell 可以让 shell 显示出所有执行的命令。

七、shell脚本应用程序

为了使 shell 程序在 Debian 系统上尽可能地具有可移植性,应该只使用 必要的软件包所提供的应用程序。

  • "aptitude search ~E",列出 必要的软件包;
  • "dpkg -L package_name |grep '/man/man.*/'",列出 package_name 软件包所提供的 man 手册。

包含用于 shell 脚本的小型应用程序的软件包:

软件包 流行度 大小 说明
dash V:883, I:997 191 小和快的 POSIX 兼容 shell,用于 sh
coreutils V:879, I:999 18307 GNU 核心工具
grep V:781, I:999 1266 GNU grep、egrep 和 fgrep
sed V:787, I:999 987 GNU sed
mawk V:437, I:997 285 小和快的 awk
debianutils V:907, I:999 223 用于 Debian 的各种工具
bsdutils V:519, I:999 356 来自 4.4BSD-Lite 的基础工具
bsdextrautils V:582, I:698 339 来自 4.4BSD-Lite 的额外的工具
moreutils V:15, I:38 244 额外的 Unix 工具

虽然 moreutils 这套工具集可能专属于 Debian 系统,它却包含了一些颇为实用的小工具。在这些工具中,尤其值得一提的是 sponge(8);当你需要覆盖原文件时,这个工具会显得特别方便。

广告合作
QQ群号:707632017

温馨提示:

1、本网站发布的内容(图片、视频和文字)以原创、转载和分享网络内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。邮箱:2942802716#qq.com。(#改为@)

2、本站原创内容未经允许不得转裁,转载请注明出处“站长百科”和原文地址。

目录