Linux系统学习笔记:BASH编程
来源:互联网 发布:做工瑕疵问题淘宝判罚 编辑:程序博客网 时间:2024/05/28 04:55
前面两篇总结了shell的交互式环境,shell不仅支持交互式使用,也支持脚本编程,shell脚本可由shell解释器执行。本篇在前面两篇的基础上总结一下BASH编程的知识。
Contents
- 变量和参数
- 位置参数
- 表达式
- 运算符
- 控制流
- if...then
- for
- while和until
- break和continue
- case
- select
- 文件描述符
- 内置命令
- shell脚本
变量和参数
上一篇已经介绍了创建变量的方法,本节进一步总结不同类型变量的创建方式。
使用 var=(element element ...) 创建数组变量。引用数组中的元素时使用 ${var[i]} , i 为下标,下标@ 复制原数组,下标 * 也复制原数组,但加双引号时它将原数组作为一个元素。给数组中单个元素赋值时可以用 var[i]=value 。 ${#var[i]} 返回元素的长度, ${#var[*]} 返回数组中元素的个数。
$ array=(Alex Harry Nancy)$ arr1=("${array[@]}")$ arr2=("${array[*]}")$ declare -adeclare -a arr1='([0]="Alex" [1]="Harry" [2]="Nancy")'declare -a arr2='([0]="Alex Harry Nancy")'declare -a array='([0]="Alex" [1]="Harry" [2]="Nancy")'$ array[1]=Jerry$ echo ${array[*]}Alex Jerry Nancy$ echo ${array[@]}Alex Jerry Nancy$ echo ${#array[*]} ${#array[1]}3 5
变量的作用域为当前脚本,可以用 export 声明变量,它将父进程的变量变为对子进程是可用的。函数中的变量默认不是局部的,作用域也为当前脚本,为了避免冲突,可以用 typeset 将它声明为局部变量。
${#var} 返回变量的长度。
${var:-default} 使用变量的值,如果值为空或未赋值,则使用给出的默认值。 ${var:=default} 和前者类似,但它同时会在值为空或未赋值时将默认值赋给变量。 ${var:?message} 可以在值为空或未赋值时显示错误信息,如果未给出 message ,则显示默认错误信息。
$ cd ${dir:?$(date +%T) error, dir not set.}-bash: dir: 10:15:29 error, dir not set.
: 可以给其后的变量赋值但不去执行它,常常用 : ${var:=default} 来给变量设置默认值。
BASH中有一种字符串模式匹配,形式为 ${varOPpattern} , OP 为: # 去除最小匹配前缀, ## 去除最大匹配前缀, % 去除最小匹配后缀, %% 去除最大匹配后缀。
$ file=/home/yeolar/a.sh$ echo ${file##/*/}a.sh$ echo ${file%/*}/home/yeolar
((var=base#n)) 语法可以给变量以其他基数赋值。
$ ((n=8#0101)); echo $n65
位置参数
位置参数保存命令和命令后的参数。可以用 set 改变位置参数的内容,但不能在脚本内改变命令名。 $# 保存参数的个数, $0 保存命令名, $1 - $n 保存命令后的参数, $@ 和 $* 保存全部参数,和数组变量类似,加双引号时 $* 作为一个参数,而 $@ 作为一组参数。 shift 左移参数。 set 初始化参数( set 没有参数时显示已设置的shell变量,还可以用它来设置shell特性)。
$ cat a.shecho "cmd: $0, args: $*, argnum: $#"echo "first arg: $1"echo "shift args..."shiftecho "cmd: $0, args: $*, argnum: $#"echo "first arg: $1"set "$@"echo "first arg: $1"set "$*"echo "first arg: $1"set a b cecho $*$ bash a.sh x y zcmd: a.sh, args: x y z, argnum: 3first arg: xshift args...cmd: a.sh, args: y z, argnum: 2first arg: yfirst arg: yfirst arg: y za b c
还有一些特殊参数: $$ 保存当前(shell)进程的PID, $! 保存最近转入后台运行的进程的PID, $? 保存上一个命令的返回状态码。
特殊参数和位置参数不能通过赋值语句改变。
表达式
可以用 let "expr" 或 ((expr)) 对算术表达式求值,多个表达式可以分别用空格和逗号分开。
$ x=1 y=1 z=0$ let "x = x * 10 + y" z=z+1$ echo $x $y $z11 1 1$ ((x = x * 10 + y, z = z + 1))$ echo $x $y $z111 1 2
条件表达式用 [[expr]] 求值。有个比较特别的运算符是 = ,在条件表达式中可以用它来判断相等。
运算符
BASH支持绝大部分C语言的运算符,有些运算符增加了一些特定语法结构中的含义,如管道。
控制流
if...then
if...then 的语法如下:
if test-command then command[elif test-command then command ...][else command] fi
为了减少缩进,常常用 ; 将 then 写到上一行。
test-command 为测试命令,可以用 test 命令进行测试,但一般使用它的同义词 [] 。
# 检查参数个数if [ $# -eq 0 ]; then # 等价于:if test $# -eq 0; then echo "Usage: cmd arg" 1>&2 exit 1fi
对于数值的测试,可以使用:
字符串的比较可以使用 = 和 != 。
下面是一些和文件相关的检查选项:
for
for 的语法如下:
for var[ in list]do commanddone
seq 为可展开为列表的表达式。可以省略 in list ,这时列表为命令的参数,即 $@ 。
# whos脚本,打印用户名和全名 Usage: whos user ...for user; do gawk -F: '{print $1, $5}' /etc/passwd | grep -i "$user"done
while和until
while 和 until 类似,区别是 until 在 do 分支执行后测试,并且是测试结果为假时循环,测试结果为真时跳出循环。
语法为:
while test-commanddo commanddoneuntil test-commanddo commanddone
# 查找拼写错误的词while read line; do if ! grep "^$line$" "$1" > /dev/null; then echo $line fidone# 猜名字rightname=yeolaruntil [ "$name" = "$rightname" ]; do echo -n "Guess: " read namedoneecho "Good, you've got it."
break和continue
break 和 continue 可以用于在 for 、 while 和 until 语句中跳出循环和继续下一循环。
case
case 用于多路选择。语法为:
case test-command in pattern) command ;; [pattern) command ;; ...]esac
pattern 可以使用 * 匹配任意字符串, ? 匹配单个字符, [...] 给出可匹配的字符, | 分离不同的选择。
# 命令选择echo -e "\ncmds: A for date, B for who, C for pwd.\n"echo -n "Enter A, B or C: "read ccase "$c" in a|A) date ;; b|B) who ;; c|C) pwd ;; *) echo "Invalid choice: $c" ;;esac
select
select 显示一个菜单,根据用户的选择给变量赋予相应的值,然后执行命令。退出 select 可以使用 break,或者 exit 退出整个脚本。
select var[ in list]do commanddone
和 for 一样,省略 in list 会用命令参数代替。 PS3 设置 select 的提示符,一般会设置为需要的提示语句。
# 命令菜单PS3="Choose what you want to do: "select c in date who pwd exit; do if [ "$c" == "" ]; then echo -e "Invalid choice.\n" continue elif [ $c = exit ]; then echo "quit" break fi echo "You choose: $c" if [ $c = date ]; then date elif [ $c = who ]; then who elif [ $c = pwd ]; then pwd fi echo ""done
文件描述符
在BASH中,使用 exec 命令执行文件描述符相关的操作:
exec n> outfile 打开outfile作为输出文件,分配文件描述符nexec n< infile 打开infile作为输入文件,分配文件描述符nexec n<&m 打开或重定向文件描述符n,作为文件描述符m的副本exec n<&- 关闭文件描述符n
内置命令
前面已经提到了很多BASH内置命令,这里做个总结和补充。
read 支持一些选项:
有个特殊的变量 REPLY ,保存读取的输入。
getopts 的语法为 getopts optstr var[ arg ...] , optstr 给出合法的字母选项, var 保存每次接收的选项的值, arg 为将处理的参数,省略将默认处理命令行参数。 optstr 以 : 开始时由脚本负责产生错误信息,否则由 getopts 自己产生。 optstr 用字母后的 : 表示选项接受值, OPTARG 保存和选项相关的值。OPTIND 保存选项的索引,起始值为1。
exec 既可执行脚本又可执行程序,它不创建新进程,把当前(shell)进程替换为要执行的内容。
trap 的用法是 trap ['command'] [signal] ,它捕获信号,执行 command ,如果没有 command ,那么重置trap 。
trap '' 2 15 # 捕获并忽略中断trap 'echo Interrupted.; exit 1' INT # 捕获中断,打印信息并退出
kill 给进程发送信号,如终止进程。后面会详细讲有关进程的内容。
shell脚本
根据本篇介绍的内容和前两篇的一些知识就可以编写shell脚本了。
像Python脚本一样可以用 #! 为脚本定义解释器。
#!/bin/bash# 或者:#!/usr/bin/env bash
- Linux系统学习笔记:BASH编程
- linux BASH编程学习笔记
- 学习笔记-Linux系统编程
- Linux学习笔记:bash脚本编程之用户交互
- Linux学习----bash脚本编程
- Linux Bash 学习笔记(1)
- Linux Bash Shell 学习笔记
- linux bash shell学习笔记
- Linux学习笔记 --Bash Scripts
- Linux学习笔记 --Bash ScriptsII
- linux 系统编程学习笔记一
- linux 系统编程学习笔记二
- linux 系统编程学习笔记三
- linux 系统编程学习笔记四
- linux 系统编程-学习笔记1
- Linux-Unix系统编程手册学习笔记
- Linux系统编程学习笔记-open函数
- Linux系统编程之基本概念--学习笔记
- 经验分享:移动客户端设计开发经验-流程篇
- 关于sudo
- Face++初识
- 奇异值分解在机器视觉中的应用
- 调用其它app的activity和让其它app调用你的activity的一些必要设置
- Linux系统学习笔记:BASH编程
- weblogic---Server subsystem failed. Reason: java.lang.NumberFormatException
- 3D世界空间单位的理解
- Linux下用gSOAP开发Web Service服务端和客户端程序(一)
- HDOJ 1858
- Linux系统学习笔记:日常使用和管理
- 不使用第三方开源包 解析xml(正则解析)
- 内核网络输出帧的处理
- JAVA异或解密字符串(自我备忘)