1.关于文件描述符和重定向:
文件描述符是与一个打开的文件或数据流相关联的整数。文件描述符0、1以及2是系统预留的.
0——stdin(标准输入)
1——stdout(标准输出)
2——stderr(标准错误)
使用“echo $?”来显示状态
amosli@amosli-pc:~/learn$ echo $? 2
amosli@amosli-pc:~/learn$ ls + 2> out.txt //没有任何输出,因为已经重定向到out.txt里面了 amosli@amosli-pc:~/learn$ cat out.txt ls: cannot access +: No such file or directory
amosli@amosli-pc:~/learn$ cmd &> output.txt amosli@amosli-pc:~/learn$ cat output.txt No command 'cmd' found, did you mean: Command 'dcmd' from package 'devscripts' (main) Command 'wmd' from package 'wml' (universe) Command 'amd' from package 'am-utils' (universe) Command 'tcmd' from package 'tcm' (universe) Command 'cme' from package 'libconfig-model-perl' (universe) Command 'cmp' from package 'diffutils' (main) Command 'qcmd' from package 'renameutils' (universe) Command 'mmd' from package 'mtools' (main) Command 'cm' from package 'config-manager' (universe) Command 'mcd' from package 'mtools' (main) Command 'icmd' from package 'renameutils' (universe) Command 'cad' from package 'rheolef' (universe) cmd: command not found
cat a* 输出所有以a开头的文件的内容
amosli@amosli-pc:~/learn$ cat a* | tee out.txt | cat -n cat: a1: Permission denied 1 a1 2 a1 #上面的代码所说的是,tee命令接收到来扑克stdin的数据,它将stdout的一份副本写入文件out.txt,同时将另一份副本作为后续命令的stdin,命令cat -n 将从stdin中接收到的每行数据前加上行号并写入stdout amosli@amosli-pc:~/learn$ cat out.txt a1 a1 amosli@amosli-pc:~/learn$ echo who is this |tee - who is this who is this
自定义文件描述符:
amosli@amosli-pc:~/learn$ exec 3<input.txt #为读取文件创建一个文件描述符 bash: input.txt: No such file or directory amosli@amosli-pc:~/learn$ echo this is a test line > input.txt amosli@amosli-pc:~/learn$ exec 3<input.txt amosli@amosli-pc:~/learn$ cat <&3 #使用自定义的文件描述3 this is a test line
文件打模式,一般有三种模式,只读,截断,和追加模式。
<操作符用于从文件中读取至stdin中。>用于截断模式(个人理解即先清空文件里的内容,再写数据进去即为所谓的截断模式)。>>操作符用于追加模式的文件写入(数据被添加到文件的现有内容之后).
2.数组和关联数组
数组分为普通数组和关联数组,普通数组只能使用整数做索引,而关联数组可以使用字符串作为数组的索引。
关联数组在很操作中相当有用,Bash4.0开始支持关联数组,4.0以前版本不支持关联数组!
数组定义的方法:
1)
array=(1 2 3 4)
2).array[index]=value;
amosli@amosli-pc:~/learn$ array_var[0]="test1" amosli@amosli-pc:~/learn$ array_var[1]="test2" amosli@amosli-pc:~/learn$ array_var[2]="test3" amosli@amosli-pc:~/learn$ array_var[3]="test4" amosli@amosli-pc:~/learn$ echo ${array_var[0]} test1 amosli@amosli-pc:~/learn$ echo ${array_var[1]} test2 amosli@amosli-pc:~/learn$ echo ${array_var[2]} test3 amosli@amosli-pc:~/learn$ echo ${array_var[3]} test4 amosli@amosli-pc:~/learn$ echo ${array_var[4]} 5 amosli@amosli-pc:~/learn$ index=5; amosli@amosli-pc:~/learn$ echo ${array_var[$index]} 6
以清单方式列出所有数组的值:index使用*来进行匹配
amosli@amosli-pc:~/learn$ echo ${array_var[*]} test1 test2 test3 test4 5 6
也可以使用@符号来做index
amosli@amosli-pc:~/learn$ echo ${array_var[@]} test1 test2 test3 test4 5 6
定义关联数组:
首先,需要使用单独的一个变量名声明为关联数组,声明语句如下:
declare -A ass_array
(1) 内嵌索引-值列表法,提供一个索引-值列表
ass_array=([index1]=value1 [index2]=value2)
(2)独立的索引-值进行赋值
ass_array[index1]=value1
ass_array[index2]=value2
举例:
amosli@amosli-pc:~/learn$ declare -A fruits_value amosli@amosli-pc:~/learn$ fruits_value[apple]="apple is 5 dollars" amosli@amosli-pc:~/learn$ fruits_value[pear]="pear is 3 dollars" amosli@amosli-pc:~/learn$ echo ${fruits_value[apple]} apple is 5 dollars
列出数组索引:
amosli@amosli-pc:~/learn$ echo ${!fruits_value[*]}#方法1 apple pear amosli@amosli-pc:~/learn$ echo ${!fruits_value[@]}#方法2 apple pear
3.使用别名
amosli@amosli-pc:~/learn$ alias install='sudo apt-get install' #为sudo apt-get install设置别名install
这个关闭当前终端即会失效。
amosli@amosli-pc:~/learn$ echo 'alias cmd="command seq"' >> ~/.bashrc #定义全局变量 amosli@amosli-pc:~/learn$ vi /home/amosli/.bashrc #使用vi删除刚才设置的别名
4.获取终端信息
使用tput和stty两款工具
获取终端的行数和列数
amosli@amosli-pc:~/learn$ tput cols 80 amosli@amosli-pc:~/learn$ tput lines 24
打印终端的名称:
amosli@amosli-pc:~/learn$ tput longname
X11 terminal emulatoramosli@amosli-pc:~/learn$
amosli@amosli-pc:~/learn$ tput setb no #更改背景色no可以取值为0-7 amosli@amosli-pc:~/learn$tput setb bold #字体加粗
5.获取、设置日期和延时
amosli@amosli-pc:~/learn$ date 2013年 12月 19日 星期四 00:13:01 CST
打印纪元时,纪元时被定义为从1970年1月1日0时0分0秒起至当前时刻的总秒数,不包括闰秒
amosli@amosli-pc:~/learn$ date +%s 1387383256
按格式输出:
amosli@amosli-pc:~$ date "+%d %b %Y" 19 12月 2013 amosli@amosli-pc:~$ date "+%d %B %Y" 19 十二月 2013
格式列表如下:
星期 %a Sat %A Saturday 月 %b Nov %B November 日 %d 19 固定日期格式mm/dd/yy %D 12/19/13 年 %y 13 %Y 2013 小时 %I/%H 00 分钟 %M 41 秒 %S 10 纳秒 %N 696308515 Unix纪元时 %s
延时
sleep number_of_seconds
6.调试脚本
打印出所执行的每一行命令
bash -x script.sh sh -x script.sh
可以在脚本使用set built-in 来启用或禁止调试打印
set -x:在执行时显示参数和命令
set +x:禁止调试
set -v:当命令进行读取时显示输入
set +v:禁止打印输入
实例:
#debug.sh for i in {1..6} do set -x echo $i set +x done echo "Script executed" amosli@amosli-pc:~/learn$ sh -x debug.sh + set -x + echo {1..6} {1..6} + set +x Script executed
直接修改脚本
#!/bin/bash -xv
7.函数和参数
定义函数
function fname() { statements; } or fname() { statements; }
函数调用
fname;
fname arg1 arg2;#传递参数
示例:
amosli@amosli-pc:~/learn$ fname(){ > echo $1,$2;#访问参数1和参数2 > echo "$@";#以列表的方式一次性打印所有参数 > echo "$*";#类似于$@,但是参数被作为单个实体 > return 0;#返回值 > } amosli@amosli-pc:~/learn$ fname 3 4; 3,4 3 4 3 4
说明:
$1第一个参数 $2第二个参数 $n第n个参数 "$@"被扩展成 "$1" "$2" "$3" "$*"扩展成"$1c$2c$3", 其中c是IFS第一个字符 "$@"使用最多, $*将所有的参数当做单个字符串
bash支持递归 ,可以了解一下Fork炸弹' :(){ :|:& };: '
导出函数,可以作用到子进程中
export -f fname
函数及命令返回值
cmd; echo $?#读取命令返回值
退出状态,成功退出,状态为0,否则,非0
8.读取命令序列输出(管道 pipe)
一个命令的输出可以作为另一个命令的输入,而这个命令的输出又会传递到另一个命令,依此类推,即是管道的思想。
$cmd1 | cmd2 | cmd3
实例:
amosli@amosli-pc:~/learn$ ls | cat -n > out.txt amosli@amosli-pc:~/learn$ cat out.txt 1 a1 2 a2 3 a3 4 debug.sh 5 input.txt 6 output.txt 7 out.txt 8 sleep.sh 9 stderr.txt 10 stdout.txt 11 test1.txt 12 uid.sh 13 variables.sh
ls 的输出(当前目录内容的列表)被传递给cat -n ,cat -n 为通过stdin所接收到输入内容加上行号,然后将输出重定向到文件out.txt
读取命令输出
cmd_output=$(COMMANDS) #subshell 子shell
or
cmd_output=`COMMANDS`#back-quote反引用
保留空格和换行符
amosli@amosli-pc:~/learn$ cat -n> text.txt amosli@amosli-pc:~/learn$ cat text.txt 1 2 3 4 amosli@amosli-pc:~/learn$ out=$(cat text.txt) amosli@amosli-pc:~/learn$ echo $out 1 2 3 4 amosli@amosli-pc:~/learn$ out2="$(cat text.txt)" #这里依然丢失了,不知道为什么,应该会保留的。 amosli@amosli-pc:~/learn$ echo $out2 1 2 3 4
out=$(cat text.txt)
echo $out #丢失所有换行符
out="$(cat text.txt)"
echo $out #保留