命令补齐相关
* 在bash中可以通过C-r激活历史记录的增量搜索模式或者用C-/ C-i或 M-/ C-i动态历史完成
常用的快捷键 bash底层采用的GNU的readline库作为底层输入接口的, readline支持两种行输入模式, emacs风格和vi风格, 默认情况下用的时emacs风格. 下面的快捷键都是针对emacs风格, 因为vi风格我很少用.
C-u 删除一行 C-k 删除到行尾 M-# 注释掉当前命令 M-. yank-last-args 将上一个命令的最后一个参数放入当前命令行(可多次使用) M-! complete-command 补齐命令名 M-$ complete-variable 补齐变量名 <tab> complete 自动补齐 M-/ complete-filename 补齐文件名 M-~ complete-username 补齐用户名 M-@ complete-hostname 补齐主机名 M-* insert-completions 通配符扩展 C-x * glob-expand-word 通配符扩展 M-? 列出所有可能的完成 C-x/ 列出所有可能的文件名完成 M-<tab> 在历史列表中进行补齐
由于readline的配置文件时INPUTRC环境变量指定,确实时~/.inputrc, 所以我们可以配置该文件的选项适合我们的需要:
"/c-w" kill-region
为了使新的绑定生效,执行re-read-init-file函数, 缺省绑定在C-x C-r上. 可以用
$bind -p
显示所有的键绑定.下面是其他一些可以用来查询的工具函数和建议的绑定
dump-functions 查询所有可用的函数 C-xf dump-variable 查询所有可用的变量 C-xv dump-macros 查询所有可用的宏 C-xm
下面是一些可用的配置变量:
bell-style 出错的报警方式 audible, visible, none edit-mode 编辑模式 emacs, vi completion-query-time expand-tile 当为on时, 按下<tab>键时,~将扩展为用户主目录 visible-stat 为on时, 目录,可执行文件,链接后加/,*,@
设置在~/.inputrc下写入类似的语句:
set visible-stats on
可以用
$bind -v
显示所有的可设置的参数. 也可以用set命令直接在命令行完成对参数的设置. 例如:
$set -o emacs 或者 $set -o vi #打开emcs或者vi方式
* bash中的常用的控制字符及其输入键
C-M [return] C-? [del] C-c intr C-d EOF C-/ quit (若C-c无效,可用此快捷键终止当前命令) C-Q 重新开始屏幕输出 C-S stop 停止屏幕输出 C-u/U 删除当前行 C-z 挂起
可以用命令stty查看这些信息
stty -a
可用help命令得到当前的shell的内置命令的列表. * 特殊的符号
! #启用历史替换 !! #引用最后一条命令 ! n #引用历史记录的第n条命令 ! -n #引用当前命令行前面n条命令 !string #引用以string开始的最后一条命令 ! ?string? #引用包含string的最后一条命令 ^string1^string2 #恢复最后的命令,并用string2替换string1
编程相关
* ~a/ 代表用户a的主目录. ~/ 代表当前用户的主目录 * 在bash中用[ !set ] 匹配不再当前set中的字符, 而不是用[^set]. 这一点在脚本编程时一定要注意 * shell中资源的优先级: 别名 关键字 函数 内置命令 脚本 可执行程序 * 取得最后执行的命令的返回值 $? * command 是shell的内置命令, 用于屏蔽函数和别名查找的. * 当自己定义的函数覆盖掉了shell的内部命令时,可以用buildin执行shell的内部命令.例子如下:
cd () { buildin cd "$@" echo "$OLDPWD=>$PWD" }
变量 -declare可以用来声明变量
-a #将变量看成数组 -f #只使用函数名 -F #显示未定义的函数名 -i #将变量看成整数 -r #使变量只读 -X #标记变量为未导出 -x #与export等价, 标记变量为导出 readonly -f #将参数解释为函数名而非变量名 readonly -n #删除该名称的只读属性 readonly -p #用内置命令打印只读名称列表 readonly -a #将名字参数解释为数组
* 声明数组
1. 第一种
names[2]=alice; name[0]=hatter; names[1]=duchess names={[2]=alice [0]=hatter [1]=duchess} names={ hutter duchess alice}
2. 第二种
declare -ar names #声明names为只读数组变量
3. 数组的一些操作
${names} #引用names的第i个元素, 用"@"和"*"引用所有的数组元素 ${#names} #引用names的第i个元素的长度 ${#names[@]} #数组的长度
4. 用unset可以删除数组的元素甚至整个数组.
* 特殊的变量
$$ #当前进程的ID $! #最后一个后台作业的进程ID $RANDOM #让shell产生一个随即数 $REPLY #read的读入结果的原始数据
参数 对于0-9的参数可以用$0,...$9来引用, 多余9的参数可以用${10}这种格式来引用. shift可以用来移动参数
函数
* 定义 在bash中支持两种函数定义方式,格式分别如下:
function functionname { shell command }
或者
functionname() { shell command }
一个例子
funciotn afunc { local var1 echo in funtion echo var1 }
* 查看
declare -f #查看会话中定义的所有的函数 declare -F #只显示函数的名称
* 删除
unset -f funtionname #删除名为functionname的函数
* 函数与脚本的区别在于:函数不在单独的子进程中运行, 而脚本在单独的子进程中运行
操作符
* 替换操作符
${vn:-w} #若vn存在且非null, 返回其值, 否则返回w (返回一个变量的值,如果没有取默认) ${vn:=w} #若vn存在且非null, 返回其值, 否则先设置vn为w,然后返回其值(设置默认值) ${vn:?w} #若vn存在且非null, 返回其值, 否则打印vn后跟w,然后退出. (用于检查变量的值, 捕捉未定义的变量 ${vn:+w} #若vn存在且非null, 返回w,否则返回null (测试变量的存在性) ${vn:offset} #返回vn从offset喀什常为length的的子串, 基于0索引, 若offset小于0,则由后往前数, 入vn为"@",length则为从offset开始的参数的个数 ${vn:offset:length}
* 模式匹配操作符
${vn#pattern} #若pattern匹配vn的开头,删除最短匹配并返回其余部分. ${vn##pattern} #若pattern匹配vn的开头,删除最长匹配并返回其余部分. ${vn%pattern} #若pattern匹配vn的结尾,删除最短匹配并返回其余部分. ${vn%%pattern} #若pattern匹配vn的结尾,删除最长匹配并返回其余部分. ${vn/pattern/str} #最长匹配被str替换一次 ${vn//pattern/str} #最长匹配被str替换所有
下面时一个匹配的例子
$ PATH=/home/cam/book/log.file.name ${PATH##/*/} => log.file.name ${PATH#/*/} => cam/book/log.file.name ${PATH%.*} => /home/cam/book/log.file ${PATH%%.*} => /home/cam/book/log
* 其他操作符
${#vn} 返回vn的串长,如若filename=alice.c,那么${#filename}=7
下面是一个利用变量的例子
vi ${grep -l "define" *.c} #编辑所有含有define的c的源文件, -l指示grep只打印文件名
条件测试和流程控制
* 若if和then放在同一行, 那么他们中间必须用";"隔开.下面是一个例子:
if [ -n "$dirname" ] && [ /( -d "$dirname" /) -a /( -x "$dirname" /) ] ; then
* 可以用!对测试取反
if [ -x "$1" -a ! -d "$1" ] ; then
* select结构 select是一个循环结构, 只能用break跳出,或者通过C-D退出循环
select name [ in list ] do command done
例如:
selectd() { PS3='directory?' select selection in $DIR_STACK ; do if [ $selection ] ; then ... break else echo 'invaild selector' fi done }
算术运算
* shell将$((和))包含的单词解释为算术表达式 * B#N表示B进制数N, B的去值2-36,省略B#默认为10. * 也可以用let语句将算术表达式求值并付给相应的变量
let x='1+4' => $x=5 let x='1<<4' => $x=16
输入和输出重定向
>1 file #即使设置了no clobber,仍然强制的将标准输出定向到file n>1 file #即使设置了no clobber,仍然强制的将文件描述符n定向到file <>file #file既做标准输出又做标准输入 n<>file #file既做文件描述符n的输出又做其输入 << label #here-document 见文本 n>& #将标准输出复制成文件描述符n n<& #将标准输入复制成文件描述符n n>&m #使文件描述符n成为输出文件描述符m的副本 n<&m #使文件描述符n成为输入文件描述符m的副本 &>file #定向标准输出和标准错误到file <&- #关闭标准输入 >&- #关闭标准输出 n>&- #关闭描述符n的输出 n<&- #关闭描述符n的输入
read 用于从文件中读取输入, 每次一行, 以"/n"结尾 eval 用与对于一个字符串进行脚本求值
信号与自陷
* 捕捉信号在shell中可以通过trap内置命令使脚本捕获对信号的处理,格式如下:
trap cmd sig1 sig2 ... #意思就是当sig1, sig2, ... 等发生的时候, 执行cmd. 然后再继续脚本的执行. cmd使定义在脚本中的函数, sig#可以使数字,也可以使信号的名称
下面是一段实例代码
trap "echo, You hit C-c" INT while true ; do sleep 60 done
* 忽略信号要想忽略掉信号的处理, 用空串代替 cmd即可
trap "" HUP
对于HUP信号,也可以用nohup指令, 如下所示:
[eval] nohup "$@" >logfile 2>&1 &
nohup是一个外置的Unix命令. * 重置信号处理
trap - sigs ... #重置sigs信号采用shell的缺省处理方式
* EXIT信号 EXIT是一个伪信号, 起作用是使得脚本无论以什么方式退出的时候都执行EXIT后面指定的代码 * DEBUG信号 DEBUG是一个伪信号, 其作用是使得脚本执行完每条语句后都执行DEBUG后面的代码
作业控制
* disown命令 disown命令可以让你失去对一个作业的控制权, 以后你就只能通过该作业的进程ID来控制该作业了. diswon -h <> nohup
- wait 内置命令wait可以用来等待作业的完成, 不带参数时等待所有 - 括号用圆括号括起来的一组命令将在子shell中执行 ** < code>"sec-13">注意与建议
* 如果代码包含变量定义和信号陷阱, 除非效率时考虑的关键因素, 否则则应该用zishell代替命令块
代码sample
1. 利用shift和case处理不带参数的选项
while [ -n "$( echo $1 | grep '^_' )" ] ; do case $1 in -a ) process option -a ;; -b ) process otion -b ;; * ) echo 'usage: alice [-a] [-b] args ...' exit 1 esac shift done
2. 处理带参数的选项
while [ -n "$( echo $1 | grep '^_' )" ] ; do case $1 in -a ) process option -a ;; -b ) process otion -b $2 is the option's argument shift ;; * ) echo 'usage: alice [-a] [-b] args ...' exit 1 esac shift done
3. 利用getopts处理参数 shell提哦功能了getopts处理参数, getopts有两个参数, 第一个是半晌字母和冒号的字符串, 每个字母均为有效选项, 如果字母后面有一个冒号,则该选项带一个参数. 第一个":"表示脚本自己处理错误. getopts从命令行中抽取相应的选项, 将其赋值给getopts的第二个参数(不带"-"). 例如:
while getopts ":ab:c" opt ; do case $opt in a ) process option -a b ) process option -b $OPTARG is the option's argument ;; c ) process option -c /? ) echo 'usage : alice [-a] [-b arg] [-c] args' exit 1 ;; esac done shift $(($OPTIND - 1 ))
配置文件
* .bash_profile 该文件只被登陆shell读取, 启动的新shell只读取.bashrc文件 * .bashrc 该文件被启动的每个shell读取 * .bash_logout bash退出时执行该文件
bash的调试器选项
set -o 命令选项 行为 noexec -n 不运行命令, 只检查语法错误 verbose -v 在运行命令前回送他们 xtrace -x 在命令处理后回送他们
提示符的定制
* 特殊字符提示符的定制中可能用到如下的特殊字符串:
/a #响铃 (007) /d #格式日期(星期,月,日) /e #ascii转义字符(003) /H #主机名 /h #主机名加"." /n #回车,换行 /s #shell的名字 /T #12小时的时间(HH:MM:SS)的当前时间 /t #24小时的当前世界(HH:MM:SS) /a # 12小时的当前时间,(am/pm) /u #当前用户的名称 /v #当前bash的版本 /V #当前bash的详细版本 /w #当前工作目录 /W #全路径的工作目录 /# #当前命令的编号 /! #当前命令的历史编号 /$ #打印$, 若uid=0,打印# /nnn #8进制的字符码 // #反斜线 /[ #开始非打印字符序列 /] #结束非打印字符序列
* PS4 PS4时bash的第四个提示符, 用于在xtrace的时候缩进. 如在.bashrc中写入如下的语句,就可以在xtrace的时候看到当前行的编号了.
PS4='$0line $LINENO' #LINENO时shell的内置变量,用于记录当前运行的脚本的行编号.
内置命令
* hash 列出bash命令的hash列表 * set 设置选项 * type 查看命令的简短说明
type -all command #查看command的所有定义的细节 type -path command #只对可执行文件和脚本,输出其路径 type -type command #输出命令的简短描述
环境变量
HISTFILE #指示当前的bash所用的历史文件 CDPATH #cd命令的搜索路径; "."不用单独设置, 永远包含 HOME #主目录 BASH_VERSINFO #shell版本信息的数组 SECONDS #启动的秒数 PWD #当前的工作目录 BASH #当前运行的shell的实例的路径名 OLDPWD #上一个工作目录 BASH_VERSION #shell的版本号 TERM #终端的类型 COLUMNS #终端的列数 LINES #终端的行数 EDITOR #编辑器
可以为一个命令配置特殊的环境变量
varname=varvalue command
给cmd指定一个名为varname的变量其值时varvalue. 用export [-p] 可以查看所有已导出的环境变量.
其他
* 更换自己的登录shell
chsh /usr/local/bin/bash
|