如何查询网站注册信息,seo小白入门教学,高米店网站建设,网站建设那个公司好文章目录 1、变量和参数的介绍#xff08;1#xff09;变量替换$(...) #xff08;2#xff09;特殊的变量类型export位置参数shift 2、引用#xff08;1#xff09;引用变量#xff08;2#xff09;转义 3、条件判断#xff08;1#xff09;条件测试结构#xff08… 文章目录 1、变量和参数的介绍1变量替换$(...) 2特殊的变量类型export位置参数shift 2、引用1引用变量2转义 3、条件判断1条件测试结构2文件测试操作符3其他比较操作符整数比较字符串比较compound comparison 4、数字常量5、变量重游1 内部变量内建变量位置参数其他的特殊参数 2 操作字符串字符串长度匹配字符串开头的子串长度索引提取子串子串削除子串替换 3 参数替换处理和(或)扩展变量 4指定变量的类型: 使用 declare 或者 typeset5变量的间接引用6$RANDOM: 产生随机整数7双圆括号结构 1、变量和参数的介绍
1变量替换
$(…) 使用 $(…) 机制来进行变量赋值这是一种比后置引用反引号更新的一种方法。 事实上这两种方法都是命令替换的一种形式。
arch$(uname -m)2特殊的变量类型
export 一个脚本只能够 export 变量到这个脚本所产生的子进程 也就是说只能够对这个脚本所产生的命令和进程起作用。 如果脚本是从命令行中调用的 那么这个脚本所 export 的变量是不能影响命令行环境的。 也就是说 子进程是不能够 export 变量来影响产生自己的父进程的环境的。
位置参数 从命令行传递到脚本的参数: $0 $1 $2 $3 . . . $0 就是脚本文件自身的名字 $1 是第一个参数 $2 是第二个参数 $3 是第三个参数 然后是第四个。 $9 之后的位置参数就必须用大括号括起来了 比如 ${10} ${11} ${12} 。 两个比较特殊的变量 $* 和 $ 表示所有的位置参数。
shift shift 命令会重新分配位置参数 其实就是把所有的位置参数都向左移动一个位置。 $1 — $2 $2 — $3 $3 — $4 等等。 原来的 $1 就消失了 但是 $0 脚本名 是不会改变的。 如果传递了大量的位置参数到脚本中 那么 shift 命令允许你访问的位置参数的数量超过 10 个 当然 {} 标记法也提供了这样的功能。
2、引用
1引用变量 双引号中通过直接使用变量名的方法来引用变量。单引号 ’ 操作与双引号基本一样 但是不允许引用变量 因为 $ 的特殊意义被关闭了。
2转义
\0xx 转换为八进制的 ASCII 码 等价于 0xx
3、条件判断
1条件测试结构 test /usr/bin/test [ ] 和 /usr/bin/[ 都是等价命令 [[ ]] 结构比 [ ] 结构更加通用。 这是一个扩展的 test 命令 是从 ksh88 中引进的。 (( )) 结构扩展并计算一个算术表达式的值
2文件测试操作符
-e 文件存在-a 文件存在。这个选项的效果与 -e 相同。 但是它已经被 “弃用” 了 并且不鼓励使用。-f 表示这个文件是一个一般文件 并不是目录或者设备文件-s 文件大小不为零-d 表示这是一个目录-b 表示这是一个块设备 软盘 光驱 等等。-c 表示这是一个字符设备 键盘 modem 声卡 等等。-p 这个文件是一个管道-h 这是一个符号链接-L 这是一个符号链接-S 表示这是一个 socket-t 文件描述符被关联到一个终端设备上。这个测试选项一般被用来检测脚本中的 stdin([ -t 0 ]) 或者 stdout([ -t 1 ]) 是否来自于一个终端。-r 文件是否具有可读权限指的是正在运行这个测试命令的用户是否具有读权限-w 文件是否具有可写权限指的是正在运行这个测试命令的用户是否具有写权限-x 文件是否具有可执行权限指的是正在运行这个测试命令的用户是否具有可执行权限-g set-group-id(sgid) 标记被设置到文件或目录上。 如果目录具有 sgid 标记的话 那么在这个目录下所创建的文件将属于拥有这个目录的用户组 而不必是创建这个文件的用户组。 这个特性对于在一个工作组中共享目录非常有用。-u set-user-id (suid) 标记被设置到文件上。 如果一个 root 用户所拥有的二进制可执行文件设置了 set-user-id 标记位的话 那么普通用户也会以 root 权限来运行这个文件。-k 设置粘贴位 对于 “粘贴位” 的一般了解 save-text-mode 标志是一个文件权限的特殊类型。 如果文件设置了这个标志 那么这个文件将会被保存到缓存中 这样可以提高访问速度。-O 判断你是否是文件的拥有者-G 文件的 group-id 是否与你的相同-N 从文件上一次被读取到现在为止 文件是否被修改过f1 -nt f2 文件 f1 比文件 f2 新f1 -ot f2 文件 f1 比文件 f2 旧f1 -ef f2 文件 f1 和文件 f2 是相同文件的硬链接! “非” —— 反转上边所有测试的结果如果没给出条件 那么返回真。
3其他比较操作符 二元比较操作符用来比较两个变量或数字。 注意整数比较与字符串比较的区别。
整数比较 -eq 等于 if [ “$a” -eq “$b” ] -ne 不等于 if [ “$a” -ne “$b” ] -gt 大于 if [ “$a” -gt “$b” ] -ge 大于等于 if [ “$a” -ge “$b” ] -lt 小于 if [ “$a” -lt “$b” ] -le 小于等于 if [ “$a” -le “$b” ] 小于在双括号中使用 ((“$a” “$b”)) 小于等于在双括号中使用 ((“ a a ab”)) 大于在双括号中使用 ((“$a” “$b”)) 大于等于在双括号中使用 ((“$a” “$b”))
字符串比较 等于 if [ “$a” “$b” ] 等于 if [ “$a” “$b” ] 与 等价。 ! 不等号 if [ “$a” ! “$b” ] 这个操作符将在 [[ … ]] 结构中使用模式匹配。 小于 按照 ASCII 字符进行排序 if [[ “$a” “$b” ]] if [ “$a” \ “$b” ] 注意 “” 使用在 [ ] 结构中的时候需要被转义。 大于 按照 ASCII 字符进行排序 if [[ “$a” “$b” ]] if [ “$a” \ “$b” ] 注意 “” 使用在 [ ] 结构中的时候需要被转义。 -z 字符串为 “null” 意思就是字符串长度为零 -n 字符串不为 “null” 。
compound comparison -a 逻辑与 exp1 -a exp2 如果表达式 exp1 和 exp2 都为真的话 那么结果为真。 -o 逻辑或 exp1 -o exp2 如果表达式 exp1 和 exp2 中至少有一个为真的话 那么结果为真。
4、数字常量 shell 脚本在默认情况下都是把数字作为 10 进制数来处理 除非这个数字采用了特殊的标记或者前缀。 如果数字以 0 开头的话那么就是 8 进制数。 如果数字以 0x 开头的话那么就是 16 进制数。 如果数字中间嵌入了 # 的话 那么就被认为是 BASE#NUMBER 形式的标记法有范围和符号限制。
# 其他进制: BASE#NUMBER
# BASE 的范围在 2 到 64 之间.
# NUMBER 的值必须使用 BASE 范围内的符号来表示 具体看下边的示例.let bin 2#111100111001101
echo binary number $bin # 31181let b32 32#77
echo base-32 number $b32 # 2315、变量重游
1 内部变量
内建变量 这些变量将会影响 bash 脚本的行为。
$BASH Bash 的二进制程序文件的路径
$ echo $BASH
/bin/bash$BASH_ENV 这个环境变量会指向一个 Bash 的启动文件 当一个脚本被调用的时候 这个启动文件将会被读取。 $BASH_SUBSHELL 这个变量用来提示子 shell 的层次。 这是一个 Bash 的新特性 直到版本 3 的 Bash 才被引入近来。 $BASH_VERSINFO[n] 这是一个含有 6 个元素的数组 它包含了所安装的 Bash 的版本信息。 这与下边的 $BASH_VERSION 很相像 但是这个更加详细一些。
# Bash version info:
for n in 0 1 2 3 4 5; doecho BASH_VERSINFO[$n] ${BASH_VERSINFO[$n]}
done
# BASH_VERSINFO[0] 3 # 主版本号
# BASH_VERSINFO[1] 00 # 次版本号。
# BASH_VERSINFO[2] 14 # 补丁次数。
# BASH_VERSINFO[3] 1 # 编译版本。
# BASH_VERSINFO[4] release # 发行状态。
# BASH_VERSINFO[5] i386-redhat-linux-gnu # 结构体系# (与变量$MACHTYPE相同。$BASH_VERSION 安装在系统上的 Bash 版本号
bash$ echo $BASH_VERSION
3.00.14(1)-releasetcsh% echo $BASH_VERSION
BASH_VERSION: Undefined variable.$DIRSTACK 在目录栈中最顶端的值。 将会受到 pushd 和 popd 的影响 这个内建变量与 dirs 命令相符 但是 dirs 命令会显示目录栈的整个内容。 $EDITOR 脚本所调用的默认编辑器 通常情况下是 vi 或者是 emacs 。 $EUID “有效” 用户 ID 。 不管当前用户被假定成什么用户 这个数都用来表示当前用户的标识号 也可能使用 su 命令来达到假定的目的。 $EUID 并不一定与 $UID 相同。 $FUNCNAME 当前函数的名字。数组形式 $FUNCNAME[0] $GLOBIGNORE 一个文件名的模式匹配列表如果在通配globbing中匹配到的文件包含有这个列表中的某个文件 那么这个文件将被从匹配到的结果中去掉。 $GROUPS 目前用户所属的组。 这是一个当前用户的组 id 列表数组 与记录在 /etc/passwd 文件中的内容一样。
root# echo $GROUPS
0
root# echo ${GROUPS[1]}
1
root# echo ${GROUPS[5]}
6$HOME 用户的 home 目录 一般是 /home/username $HOSTNAME hostname 放在一个初始化脚本中 在系统启动的时候分配一个系统名字。 然而 gethostname() 函数可以用来设置这个 Bash 内部变量 $HOSTNAME 。 $HOSTTYPE 主机类型 就像 $MACHTYPE 用来识别系统硬件。
bash$ echo $HOSTTYPE
i686$IFS 内部域分隔符 这个变量用来决定 Bash 在解释字符串时如何识别域 或者单词边界。 $IFS 默认为 空白空格 制表符和换行符 但这是可以修改的 比如 在分析逗号分隔的数据文件时 就可以设置为逗号。 注意 $* 使用的是保存在 $IFS 中的第一个字符。 $IGNOREEOF 忽略 EOF : 告诉 shell 在 log out 之前要忽略多少文件结束符control-D。 $LC_COLLATE 常在 .bashrc 或 /etc/profile 中设置 这个变量用来控制文件名扩展和模式匹配的展开顺序。 如果 $LC_COLLATE 设置得不正确的话 LC_COLLATE 会在文件名匹配filename globbing中产生不可预料的结果。 $LC_CTYPE 这个内部变量用来控制通配globbing和模式匹配中的字符串解释。 $LINENO 这个变量用来记录自身在脚本中所在的行号。 这个变量只有在脚本使用这个变量的时候才有意义并且这个变量一般用于调试目的。 $MACHTYPE 机器类型。标识系统的硬件。
bash$ echo $MACHTYPE
i686$OLDPWD 之前的工作目录“OLD-print-working-directory” 就是之前你所在的目录 $OSTYPE 操作系统类型 $PATH 可执行文件的搜索路径 一般为 /usr/bin/ /usr/X11R6/bin/ /usr/local/bin 等等。 $PIPESTATUS 这个数组变量将保存最后一个运行的前台管道的退出状态码。 相当有趣的是 这个退出状态码和最后一个命令运行的退出状态码并不一定相同。 $PPID 进程的 $PPID 就是这个进程的父进程的进程 IDpid。 $PROMPT_COMMAND 这个变量保存了在主提示符 $PS1 显示之前需要执行的命令。 $PS1 这是主提示符 可以在命令行中见到它。 $PS2 第二提示符 当你需要额外输入的时候 你就会看到它。 默认显示 “” 。 $PS3 第三提示符 它在一个 select 循环中显示 。 $PS4 第四提示符 当你使用 -x 选项来调用脚本时 这个提示符会出现在每行输出的开头。 默认显示 “” 。 $PWD 工作目录你当前所在的目录 $REPLY 当没有参数变量提供给 read 命令的时候 这个变量会作为默认变量提供给 read 命令。 也可以用于 select 菜单 但是只提供所选择变量的编号 而不是变量本身的值。 $SECONDS 这个脚本已经运行的时间以秒为单位。 $SHELLOPTS shell 中已经激活的选项的列表 这是一个只读变量。
bash$ echo $SHELLOPTS
braceexpand:hashall:histexpand:monitor:history:interactivecomments:emacs$SHLVL Shell 级别 就是 Bash 被嵌套的深度。 如果是在命令行中 那么 $SHLVL 为 1 如果在脚本中那么 $SHLVL 为 2 。 $TMOUT 如果 $TMOUT 环境变量被设置为非零值 time 的话 那么经过 time 秒后 shell 提示符将会超时。 这将会导致登出logout。 $UID 用户 ID 号。当前用户的用户标识号 记录在 /etc/passwd 文件中
位置参数 $0 $1 $2 等等。 位置参数 从命令行传递到脚本 或者传递给函数 或者 set 给变量 $# 命令行参数或者位置参数的个数 $* 所有的位置参数都被看作为一个单词。 “$*” 必须被引用起来。 $ 与 $* 相同 但是每个参数都是一个独立的引用字符串 这就意味着 参数是被完整传递的 并没有被解释或扩展。 这也意味着 参数列表中每个参数都被看作为单独的单词。 “$” 应该被引用起来。
其他的特殊参数 $- 传递给脚本的标记使用 set 命令。 $! 运行在后台的最后一个作业的 PID进程 ID $_ 这个变量保存之前执行的命令的最后一个参数的值 $? 命令 函数 或者是脚本本身的退出状态码 $$ 脚本自身的进程 ID。 $$ 变量在脚本中经常用来构造 “唯一的” 临时文件名
2 操作字符串 Bash 所支持的字符串操作的数量多的令人惊讶。 但是不幸的是 这些工具缺乏统一的标准。 一些是参数替换的子集 而另外一些则受到 UNIX expr 命令的影响。 这就导致了命令语法的不一致 还会引起冗余的功能 但是这些并没有引起混乱。
expr --help
用法expr 表达式或expr 选项--help 显示此帮助信息并退出--version 显示版本信息并退出将 表达式 的值打印到标准输出。以下运算符按优先级从低到高排列不同
优先级之间以空行隔开。表达式 可以是参数1 | 参数2 若 参数1 的值不为 0 或 null则返回 参数1否则返回 参数2参数1 参数2 若两边的值都不为 0 或 null则返回 参数1否则返回 0参数1 参数2 参数1 小于 参数2参数1 参数2 参数1 小于或等于 参数2参数1 参数2 参数1 等于 参数2参数1 ! 参数2 参数1 不等于 参数2参数1 参数2 参数1 大于或等于 参数2参数1 参数2 参数1 大于 参数2参数1 参数2 计算 参数1 加 参数2 的和参数1 - 参数2 计算 参数1 减 参数2 的差参数1 * 参数2 计算 参数1 乘以 参数2 的积参数1 / 参数2 计算 参数1 除以 参数2 的商参数1 % 参数2 计算 参数1 除以 参数2 的余数字符串 : 正则 在 字符串 起始处进行 正则 的模式匹配match 字符串 正则 等于 字符串 : 正则substr 字符串 位置 长度 求 字符串 的子串位置 从 1 开始数index 字符串 字符 在 字符串 中搜索 字符 中任何一个返回其索引如未找到则返回 0length 字符串 字符串 的长度 记号 将 记号 解释为字符串即使它是一个关键字例如 match或者运算符例如 /( 表达式 ) 表达式 的值请注意由于 shell 这一层的存在可能有许多运算符需要转义或者加引号。
如果两个 参数 都是数字比较运算符就是算术比较否则就是字典序比较。
模式匹配会返回 \( 和 \) 之间的字符串匹配的字符串若没有匹配则返回 null
如果未使用 \( 和 \)则会返回匹配的字符的个数若没有匹配则返回 0。若 表达式 的值既不是 null 也不是 0则退出状态为 0若 表达式 的值为 null
或者 0则退出状态为 1如果 表达式 的句法无效则退出状态为 2如果有错误
发生则退出状态为 3。GNU coreutils 在线帮助https://www.gnu.org/software/coreutils/
请向 http://translationproject.org/team/zh_CN.html 报告任何翻译错误
完整文档 https://www.gnu.org/software/coreutils/expr
或者在本地使用info (coreutils) expr invocation字符串长度
语法
${#string}
expr length $string
expr $string : .*示例
stringZabcABC123ABCabcecho ${#stringZ} # 15
echo $(expr length $stringZ) # 15
echo $(expr $stringZ : .*) # 15${#var} 字符串长度 (变量$var得字符个数) 。 对于 array 来说 ${#array} 表示的是数组中第一个元素的长度。 例外情况
${#*} 和 ${#} 表示位置参数的个数。对于数组来说 ${#array[*]} 和 ${#array[]} 表示数组中元素的个数。
匹配字符串开头的子串长度
语法
expr match $string $substring
# $substring 是一个正则表达式.
expr $string : $substring
# $substring是一个正则表达式.示例
stringZabcABC123ABCabc
# |------|echo $(expr match $stringZ abc[A-Z]*.2) # 8
echo $(expr $stringZ : abc[A-Z]*.2) # 8索引
语法
expr index $string $substring
# 在字符串 $string 中所匹配到的 $substring 第一次所出现的位置示例
stringZabcABC123ABCabcecho $(expr index $stringZ C12) # 6 # C 字符的位置
echo $(expr index $stringZ 1c) # 3
# c (in #3 position) matches before 1.提取子串
语法
${string:position}
# 在 $string 中从位置 $position 开始提取子串.
# 如果 $string 是 * 或者 那么将会提取从位置 $position 开始的位置参数.${string:position:length}
# 在 $string 中从位置 $position 开始提取 $length 长度的子串.示例
stringZabcABC123ABCabc
# 0123456789.....
# 0-based indexing.echo ${stringZ:0} # abcABC123ABCabc
echo ${stringZ:1} # bcABC123ABCabc
echo ${stringZ:7} # 23ABCabc
echo ${stringZ:7:3} # 23A# 提取子串长度为3.# 能不能从字符串的右边(也就是结尾)部分开始提取子串?
echo ${stringZ:-4} # abcABC123ABCabc
# 默认是提取整个字符串 就象${parameter:-default}一样.
# 然而 . . . echo ${stringZ:(-4)} # Cabc
echo ${stringZ: -4} # Cabc
# 这样 它就可以工作了.
# 使用圆括号或者添加一个空格可以转义这个位置参数.如果 $string 参数是 * 或 那么将会从 $position 位置开始提取 $length 个位置参数 但是由于可能没有 $length 个位置参数了那么就有几个位置参数就提取几个位置参数。
echo ${*:2} # 打印出第2个和后边所有的位置参数.
echo ${:2} # 同上.echo ${*:2:3} # 从第2个开始 连续打印3个位置参数.#./t.sh 1 2 3 4 5 6
#2 3 4 5 6
#2 3 4 5 6
#2 3 4语法
expr substr $string $position $length
# 在 $string 中从 $position 开始提取 $length 长度的子串.expr match $string \($substring\)
# 从 $string 的开始位置提取 $substring $substring 是正则表达式.expr $string : \($substring\)
# 从 $string 的开始位置提取 $substring $substring 是正则表达式.示例
stringZabcABC123ABCabc
#
echo $(expr match $stringZ \(.[b-c]*[A-Z]..[0-9]\)) # abcABC1
echo $(expr $stringZ : \(.[b-c]*[A-Z]..[0-9]\)) # abcABC1
echo $(expr $stringZ : \(.......\)) # abcABC1
# 上边的每个echo都打印出相同的结果.语法
expr match $string .*\($substring\)
# 从 $string 的结尾提取$substring $substring 是正则表达式.
expr $string : .*\($substring\)
# 从 $string 的结尾提取 $substring $substring 是正则表达式.示例
stringZabcABC123ABCabc
# echo $(expr match $stringZ .*\([A-C][A-C][A-C][a-c]*\)) # ABCabc
echo $(expr $stringZ : .*\(......\)) # ABCabc子串削除
语法
${string#substring}
# 从 $string 的开头位置截掉最短匹配的 $substring .
${string##substring}
# 从 $string 的开头位置截掉最长匹配的 $substring .示例
stringZabcABC123ABCabc
# |----|
# |----------|echo ${stringZ#a*C} # 123ABCabc
# 截掉a到C之间最短的匹配字符串.echo ${stringZ##a*C} # abc
# 截掉a到C之间最长的匹配字符串.语法
${string%substring}
# 从 $string 的结尾位置截掉最短匹配的 $substring .
${string%%substring}
# 从 $string 的结尾位置截掉最长匹配的 $substring.示例
stringZabcABC123ABCabc
# ||
# |------------|echo ${stringZ%b*c} # abcABC123ABCa
# 从$stringZ的结尾位置截掉b到c之间最短的匹配. echo ${stringZ%%b*c} # a
# 从$stringZ的结尾位置截掉b到c之间最长的匹配.子串替换
语法
${string/substring/replacement}
# 使用 $replacement 来替换第一个匹配的 $substring .${string//substring/replacement}
# 使用 $replacement 来替换所有匹配的 $substring .示例
stringZabcABC123ABCabc
echo ${stringZ/abc/xyz} # xyzABC123ABCabc# 使用xyz来替换第一个匹配的abc.echo ${stringZ//abc/xyz} # xyzABC123ABCxyz# 用xyz来替换所有匹配的abc.语法
${string/#substring/replacement}
# 如果 $substring 匹配 $string 的开头部分 那么就用 $replacement 来替换 $substring .${string/%substring/replacement}
# 如果 $substring 匹配 $string 的结尾部分 那么就用 $replacement 来替换 $substring.
示例
stringZabcABC123ABCabcecho ${stringZ/#abc/XYZ} # XYZABC123ABCabc# 用XYZ替换开头的abc.echo ${stringZ/%abc/XYZ} # abcABC123ABCXYZ# 用XYZ替换结尾的abc.3 参数替换
处理和(或)扩展变量 ${parameter} 与 $parameter 相同 也就是变量 parameter 的值。 ${parameter-default} ${parameter:-default} ${parameter-default} – 如果变量 parameter 没被声明 那么就使用默认值。 ${parameter:-default} – 如果变量 parameter 没被设置 那么就使用默认值。 ${parameterdefault} ${parameter:default} ${parameterdefault} – 如果变量 parameter 没声明 那么就把它的值设为 default。 ${parameter:default} – 如果变量 parameter 没设置 那么就把它的值设为 default。 这两种形式基本上是一样的。 只有在变量 $parameter 被声明并且被设置为 null 值的时候 才会引起这两种形式的不同。 ${parameteralt_value} ${parameter:alt_value} ${parameteralt_value} – 如果变量 parameter 被声明了 那么就使用 alt_value 否则就使用 null 字符串。 ${parameter:alt_value} – 如果变量 parameter 被设置了 那么就使用 alt_value 否则就使用 null 字符串。 这两种形式绝大多数情况下都一样。 只有在 parameter 被声明并且设置为 null 值的时候 多出来的这个: 才会引起这两种形式的不同。 ${parameter?err_msg} ${parameter:?err_msg} ${parameter?err_msg} – 如果 parameter 已经被声明 那么就使用设置的值 否则打印 err_msg 错误消息。 ${parameter:?err_msg} – 如果 parameter 已经被设置 那么就使用设置的值 否则打印 err_msg 错误消息。 这两种形式绝大多数情况都是一样的。 和上边所讲的情况一样 只有在 parameter 被声明并设置为 null 值的时候 多出来的:才会引起这两种形式的不同。
4指定变量的类型: 使用 declare 或者 typeset declare 或者 typeset 内建命令这两个命令是完全一样的)允许指定变量的具体类型。 在某些编程语言中 这是指定变量类型的一种很弱的形式。 declare 命令是从 Bash 2.0 之后才被引入的命令。 typeset 也可以用在 ksh 的脚本中。
declare/typeset 选项
-r 只读
declare -r var1declare -r var1 与 readonly var1 是完全一样的 这和 C 语言中的 const 关键字一样 都用来指定变量为只读。 如果你尝试修改一个只读变量的值那么会产生错误信息。
-i 整型
declare -i number
# 脚本将会把变量number按照整型进行处理。number3
echo Number $number # Number 3numberthree
echo Number $number # Number 0
# 脚本尝试把字符串three作为整数来求值译者注: 当然会失败 所以出现值为0。如果把一个变量指定为整型的话 那么即使没有 expr 或者 let 命令 也允许使用特定的算术运算。
n6/3
echo n $n # n 6/3declare -i n
n6/3
echo n $n # n 2-a 数组
declare -a indices变量 indices 将被视为数组。
-f 函数
declare -f如果在脚本中使用declare -f 而不加任何参数的话 那么将会列出这个脚本之前定义的所有函数。
declare -f function_name如果在脚本中使用declare -f function_name这种形式的话 将只会列出这个函数的名字。
-x export
declare -x var3这句将会声明一个变量 并作为这个脚本的环境变量被导出。
-x var$value
declare -x var3373declare 命令允许在声明变量类型的同时给变量赋值。
示例
#!/bin/bashfunc1() {echo This is a function.
}declare -f # 列出前面定义的所有函数。
echodeclare -i var1 # var1是个整型变量。
var12367
echo var1 declared as $var1
var1var11 # 整型变量的声明并不需要使用let命令。
echo var1 incremented by 1 is $var1.
# 尝试修改一个已经声明为整型变量的值。
echo Attempting to change var1 to floating point value, 2367.1.
var12367.1 # 产生错误信息 并且变量并没有被修改。
echo var1 is still $var1echodeclare -r var213.36 # declare允许设置变量的属性# 同时给变量赋值。
echo var2 declared as $var2 # 试图修改只读变量的值。
var213.37 # 产生错误消息 并且从脚本退出。echo var2 is still $var2 # 将不会执行到这行。exit 0 # 脚本也不会从此处退出。5变量的间接引用 假设一个变量的值是第二个变量的名字。 那么我们如何从第一个变量中取得第二个变量的值呢? 比如如果 aletter_of_alphabet 并且 letter_of_alphabetz 那么我们能够通过引用变量 a 来获得 z 么? 这确实是可以做到的 它被称为间接引用。 它使用 eval var1\$$a 这种不平常的形式。
#!/bin/bash# ind-ref.sh: 间接变量引用.
# 访问一个以另一个变量内容作为名字的变量的值.(译者注: 怎么译都不顺)aletter_of_alphabet # 变量a的值是另一个变量的名字.
letter_of_alphabetzecho# 直接引用.
echo a $a # a letter_of_alphabet# 间接引用.
eval a\$$a
echo Now a $a # 现在 a zecho# 现在 让我们试试修改第二个引用的值.ttable_cell_3
table_cell_324
echo \table_cell_3\ $table_cell_3 # table_cell_3 24
echo -n dereferenced \t\
eval echo \$$t # 解引用 t 24
# 在这个简单的例子中 下面的表达式也能正常工作么(为什么?).
# eval t\$$t; echo \t\ $techottable_cell_3
NEW_VAL387
table_cell_3$NEW_VAL
echo Changing value of \table_cell_3\ to $NEW_VAL.
echo \table_cell_3\ now $table_cell_3
echo -n dereferenced \t\ now
eval echo \$$t
# eval 带有两个参数 echo 和 \$$t (与$table_cell_3等价)echo# (感谢 Stephane Chazelas 澄清了上边语句的行为.)# 另一个方法是使用${!t}符号 见Bash 版本2小节的讨论. 45 # 也请参考 ex78.sh.exit 0变量的间接引用到底有什么应用价值? 它给 Bash 添加了一种类似于 C 语言指针的功能 比如 在表格查找中的用法。
6$RANDOM: 产生随机整数 $RANDOM 是 Bash 的内部函数 (并不是常量) 这个函数将返回一个伪随机整数 范围在 0 - 32767 之间。 它不应该被用来产生密匙。
#!/bin/bash
# 每次调用$RANDOM都会返回不同的随机整数.
# 一般范围为: 0 - 32767 (有符号的 16-bit整数).MAXCOUNT10
count1echo
echo $MAXCOUNT random numbers:
echo -----------------while [ $count -le $MAXCOUNT ] # 产生10 ($MAXCOUNT)个随机整数.
donumber$RANDOMecho $numberlet count 1 # 增加计数.
done
echo -----------------# 如果你需要在特定范围内产生随机整数, 那么使用modulo(模)操作.(译者注: 事实上, 这不是一个非常 好的办法. 理由见man 3 rand)
# 取模操作会返回除法的余数.
RANGE500echonumber$RANDOM
let number % $RANGE
# ^^
echo Random number less than $RANGE --- $numberecho# 如果你需要产生一个大于某个下限的随机整数.
# 那么建立一个test循环来丢弃所有小于此下限值的整数. FLOOR200number0 #初始化
while [ $number -le $FLOOR ]
donumber$RANDOM
done
echo Random number greater than $FLOOR --- $number
echo# 让我们对上边的循环尝试一个小改动, 如下:
# let number $RANDOM $FLOOR
# 这将不再需要那个while循环, 并且能够运行的更快.
# 但是, 这可能会产生一个问题, 思考一下是什么问题?
# 结合上边两个例子, 来在指定的上下限之间来产生随机数.
number0 #initialize
while [ $number -le $FLOOR ]
donumber$RANDOMlet number % $RANGE # 让$number依比例落在$RANGE的范围内.
done
echo Random number between $FLOOR and $RANGE --- $number
echo# 产生二元值, 就是, true 或 false 两个值.
BINARY2
T1
number$RANDOM
let number % $BINARY
# 注意 let number 14 将会给出一个更好的随机分配. #(译者注: 正如man页中提到的, 更 高位的随机分布更加平均)
# (右移14位将把所有的位全部清空, 除了第15位, 因为有符号, 第16位是符号位). #取模操作使用低位来 产生随机数会相对不平均)
if [ $number -eq $T ]
thenecho TRUE
elseecho FALSE
fi echo# 抛骰子.
SPOTS6 # 模 6 给出的范围是 0 - 5.
# 加 1 会得到期望的范围
# 感谢, Paulo Marcel Coelho Aragao, 对此进行的简化.
die10
die20
# 是否让SPOTS7会比加1更好呢? 解释行或者不行的原因?
# 每次抛骰子, 都会给出均等的机会.
let die1 $RANDOM % $SPOTS 1 # 抛第一次.
let die2 $RANDOM % $SPOTS 1 # 抛第二次.
# 上边的算术操作中, 哪个具有更高的优先级呢 --
# 模(%) 还是加法操作()?
let throw $die1 $die2
echo Throw of the dice $throw
echo
exit7双圆括号结构 与 let 命令很相似 ((…)) 结构允许算术扩展和赋值。 举个简单的例子 a$(( 5 3 )) 将把变量 “a” 设为 “5 3” 或者 8 。 然而 双圆括号结构也被认为是在 Bash 中使用 C 语言风格变量操作的一种处理机制。
#!/bin/bash
# 使用((...))结构操作一个变量, C语言风格的变量操作.echo((a 23)) # C语言风格的变量赋值, 两边允许有空格.
echo a (initial value) $a((a)) # C语言风格的后置自加.
echo a (after a) $a((a--)) # C语言风格的后置自减.
echo a (after a--) $a((a)) # C语言风格的前置自加.
echo a (after a) $a((--a)) # C语言风格的前置自减.
echo a (after --a) $aecho########################################################
# 注意: 就像在C语言中一样, 前置或后置自减操作
# 会产生一些不同的副作用.n1
let --n echo True || echo False # False
n1
let n-- echo True || echo False # True# 感谢, Jeroen Domburg.
########################################################echo((t a 45 ? 7 : 11)) # C语言风格的三元操作.
echo If a 45, then t 7, else t 11.
echo t $t # Yes!echo# ------------
# 复活节彩蛋!
# ------------
# Chet Ramey显然偷偷摸摸的将一些未公开的C语言风格的结构
# 引入到了Bash中 (事实上是从ksh中引入的, 这更接近些).
# 在Bash的文档中, Ramey将((...))称为shell算术运算,
# 但是它所能做的远远不止于此.
# 不好意思, Chet, 现在秘密被公开了.# 你也可以参考一些 for 和 while 循环中使用((...))结构的例子.# 这些只能够在Bash 2.04或更高版本的Bash上才能运行.exit 0☆