linux shell(一)
近来在看《LINUX SHELL脚本攻略》,感觉还不错,对于入门和梳理以前知识还是挺适合的,以下是只是本人对书上内容的摘要,mark下来方便自己查看。
1. shebang
1.1 shell脚本文本一般以 #!/bin/bash 开头,使用脚本运行必须含有这一行,shell程序读取脚本的首行时,会识别/bin/bash,并在内部以如下命令行执行该脚本:
$ /bin/bash myscript.sh
另外一种执行方式是,将脚本作为sh 的命令行参数:
$ sh myscript.sh
1.2 配置文件(~/.bashrc), 历史记录文件(~/.bash_history)
2. 终端打印
2.1 echo
$ echo hello world ! #可以这样在命令行使用,但无法在所要显示的文本中使用,因为在bash shell中被用作命令定界符。
$ echo "hello world \!" #!在双引号中需要进行转义
$ echo 'hello world !' #注意bash不会对单引号中的变量(如$var)求值,而是照原样显示。
默认情况下,echo会将一个换行符追加到文本尾部。可以使用-n来忽略结尾换行符。
$ ehco -e "1\t2\t3" #ehco -e 包含转义序列
1 2 3
$echo -e "\e[1;31m red text \e[0m" #打印彩色文本
2.2 printf
printf "%-5s %-10s %-4s\n" NO Name Mark
printf "%-5s %-10s %-4.2f\n" 01 Tom 90.3456
printf "%-5s %-10s %-4.2f\n" 02 Jack 89.2345
printf "%-5s %-10s %-4.2f\n" 03 Jeff 98.4323
%s, %c, %d和%f都是格式替代符,其对应的参数可以置于带引号的格式字符串之后。
3. 变量与环境变量
3.1 prepare
$ pgrep vi # 可以使用pgrep获取vi的进程ID
6325
然后通过以下命令获取与该进程相关的环境变量
$ cat /proc/6325/environ (或者cat /proc/6325/environ | tr '\0' '\n' 进行格式化输出)
HOSTNAME=localhost.localdomainTERM=vt100SHELL=/bin/bashHISTSIZE=1000SSH_CLIENT=192.168.3.200 51845 22SSH_TTY=/dev/pts/1JRE_HOME=/usr/local/java/jdk1.7.0.....
3.2 赋值与引用
var=value赋值操作(注意:var = value 是相等操作,注意区分)
+变量名或
+{变量名} 进行引用变量值
$ echo $var # or echo ${var}
设置环境变量使用export命令:
$ export PATH="$PATH:/home/user/java"
(或者
PATH="$ PATH:/home/user/java" export PATH)
3.3 其他
3.3.1 获取字符串长度
length=${#var}
3.3.2 识别当前sh ell版本
echo $SHEEL 或 echo $0
3.3.3 判断是否超级用户
echo $UID # root用户的UID是0
3.3.4 修改bash提示字符串(username@hostname:~$)
在文件~/.bash文件中PS1=…..
3.3.5 使用函数添加环境变量
prepend() { [ -d "$2" ] && eval $1=\"$2\$\{$1:+':'\$$1\}\" && export $1 ; }
remark:
${parameter:+expression} #如果parameter有值且不为空,则使用expression的值
4. 进行数学运算
可以利用let、(())和[]执行基本的算数操作。进行高级操作时可以使用expr和bc。普通的变量赋值方法定义数值时,会被存储为字符串,可以通过一些方法使它能像数字一样进行处理。
4.1 使用let可以直接执行基本的算数操作。
$ a=5+2
$ b=3+2
$ let result=a+b
$ echo $result
自加: leta++,自减: let b–
$ let a+=6 #(等同于a=a+6)
$ b-=6 #(等同于b=b-6)
4.2 使用[](和let类似)
result=$[ a + b + 10] 或者 result=$[ $a + $b + 10]
4.3 使用(()),变量名前需要加$;使用expr也行
result=$(( a + 50 ))
result=$(expr $a + 50)
4.4 以上只用于执行整数,如使用浮点数,可用bc,并应用一些高级函数
echo "4 * 0.56" | bc
echo "scale=1;1/6" | bc
echo "obase=2;100" | bc # 转换成二进制
echo "obase=10;ibase=2;1100" | bc #二进制转十进制
5. 文件描述符和重定向
5.1 系统预留的文件描述符
0 —— stdin(标准输入)
1 —— stdout(标准输出)
2 —— stdin(标准错误)
5.2 将输出文本重定向到一个文件
echo "demo test file" > temp.txt #先清空,再写入
echo " demo test file2" >> temp.txt #在文件末尾进行追加
将文件重定向到命令:
$ cmd < file
重定向内部文件块,使用<<EOF>...EOF之间的所有文本行都会成为stdin数据
使用tee来实现将数据重定向到文件,同时提供一份重定向数据的副本作为后续命令的stdin:
格式如下:
$ command | tee file1 file2
eg :
$ cat a* | tee out.txt | cat -n # tee 只能从stdin中读取
/dev/null,是特殊的设备文件,将接收到的任何数据都会被丢弃。null设备通常称为黑洞。
$ cmd 2>/dev/null # 将错误信息丢弃
5.3 自定义文件描述符
使用exec命令创建自定义文件描述符
文件打开模式:
- 只读模式(<从文件中读取至stdin)
$ echo a test line > testinput.txt
$ exec 3<testinput.txt
$ cat <&3
a test line
- 截断模式(>截断模式的文件写入)
$ exec 4>testoutput.txt
$ echo newline >&4
$ cat testoutput.txt
newline
- 追加模式(>>追加模式的文件写入)
$ exec 5>>testinput.txt
$ echo appended line >&5
$ cat testinput.txt
a test line
appended line
6. 数组与关联数组
普通数组只能使用整数作为数组索引,关联数组则可以使用字符作为数组索引
6.1 定义普通数组
array_var=(1,2,3,4,5) 或
array_var[0]="1"
array_vat[1]="2"
6.2 操作数组一些方法
array_var[0]="1";
array_var[2]="2";
echo ${array_var[0]} # 取索引为0的值
array_var[0]="1";
array_var[2]="2";
echo ${array_var[*]} # 获取数组中所有值
array_var[0]="1";
array_var[2]="2";
echo ${array_var[@]} # 获取数组中所有值
array_var[0]="1";
array_var[2]="2";
echo ${#array_var[*]} # 打印数组长度
6.3 定义关联数组
declare -A ass_array
ass_array=([a]='100' [b]='200')
echo "the a is ${ass_array[a]}"
# 列出数组索引通过以下方式:
echo ${!ass_array[*]}
7. 使用别名
创建别名(临时的,关闭当前终端就失效):
alias new_command = 'command sequence'
放入~/.bashrc文件中,可以一直保持作用:
$ 'alias cmd="command sequence"' >> ~/.bashrc
字符\对命令实施转义,可以执行原来的命令:
$ \ command
8. 日期和延时
8.1 读取日期
$ date
$ date +%s # 读取纪元时
1445323477
$ date --date "Mon Oct 19 23:43:43 PDT 2015" +%s # 转换成纪元时
8.2 脚本中生成延时
$ sleep no_of_seconds
$ sleep 1 # 延时1秒
9. 调试脚本
9.1 启动跟踪调试shell脚本
$ bash -x script.sh
9.2 针对脚本部分命令与脚本进行打印输出
set -x : 执行时显示参数和命令
set +x: 禁止调试
set -v:当命令进行读取时显示输入
set +v:禁止打印输入
可以设置成#!/bin/bash -xv,即可启用调试功能。
9.3 将#!/bin/bash改成#!/bin/bash -xv,也可以启用调试功能
10. 函数和参数
10.1 定义函数:
funciton a() { statement; }
或
a() { statement; }
10.2 调用函数:
$ a; # 执行函数
$ a arg1 arg2; # 执行函数,并传递参数
10.3 参数传递,并由脚本进行访问:
# fname函数定义,访问函数参数的方法如下
fname() {
echo $1, $2; # 访问参数1和参数2,类似$n,指第n个参数
echo "$@"; # 以列表的方式一次性打印所有参数
echo "$*"; # 类似于$@,但是参数作为单个实体
return 0; # 返回值
}
10.4 其他
支持递归。
导出函数:export -f fname
10.5 读取命令序列输出
这些命令被称为过滤器(filter)。使用管道(|)可以连接每个一个过滤器:
$ cmd1 | cmd2 | cmd3
$ ls | cat -n > out.txt
采用子shell方式存储命令序列的输出:
# 子shell生成独立进程,不会对当前shell产生影响
$ cmd_output=$(ls | cat -n); echo $cmd_output
$ cmd_output=`ls | cat -n`; echo $cmd_output # 效果同上
11. read
# 读取2个字符并存入var变量
$ read -n 2 var
$ echo $var
# 不回显方式读取
$ read -s var
# 显示提示信息
$ read -p "enter input: " var
# 在特定时限内读取
$ read -t timeout var
# 用定界符结束输入行
$ read -d delim_char var
12. 运行命令直到成功
12.1 定义函数
repeat() {
while true
do
$@ && return
done
}
更快捷的做法是:
repeat() { while :; do $@ && return; done }
增加延时:
repeat() { while :; do $@ && return; sleep 30; done }
13. 字段分隔符和迭代器
13.1 内部字段分隔符IFS,IFS是存储定界符的环境变量,当前shell环境默认使用的界定字符串。
oldIFS=$IFS;
IFS=":";
for item in $line; ......
IFS=$oldIFS
13.2 for 循环
for var in list; do commands; done;
for i in (1..10); do commands; done;
for((i=0; i<10; i++)) { commands; }
13.3 while 循环
while condition; do commands; done;
13.4 until 循环
x=0;
until [ $x -eq 9 ]; # [ $x -eq 9 ] is the condition
do let x++;
echo $x;
done;
14. 比较与测试
14.1 if, else if, else (可以进行嵌套)
if condition;
then
command;
fi
14.2 else if 和 else
if condition;
then
command;
elif condition;
then
command;
else
command;
fi
14.3 使用逻辑运算符方式
[ condition ] && action; # 如果condition为真,则执行action
[ condition ] || action; # 如果condition为假,则执行action
14.4 算术比较(注意空格)
[ $var -eq 0 ] or [ $var -eq 0 ]
操作符:-gt:大于。
-lt:小于。
-ge:大于或等于。
-le:小于或等于。
-eq:等于。
-ne:不等于。
14.5 逻辑与,逻辑或
[ $var -gt 1 -a $var -lt 10 ] # -a 表示逻辑与
[ $a -eq 1 -o $b -ne 0 ] # -o 表示逻辑或
14.6 文件系统相关判断
[ -f $file_var ]:如果给定的变量包含正常的文件路径或文件名,则返回真
[ -x $file_var ]:如果给定的变量包含的文件可执行,则返回真
...等等
14.7 字符串比较(最好使用双中括号)
[[ $str1 = $str2 ]] 或 [[ $str1 == $str2 ]] # 判断是否相等
[[ $str1 != $str2 ]] # 判断不相等
[[ $str1 > $str2 ]], [[ $str1 < $str2 ]] #判断字母序
[[ -z $str ]] #包含的是空字符,则返回真
[[ -n $str ]] #包含的是非空字符,则返回真
14.8 使用&&和||也可以将多个条件进行组合
if [[ $str1 != $str2 ]] && [[ -z $str1 ]] || [[ -n $str2 ]]
14.9 使用test,可不用[]
if test $str1 = $str2 # 同 if [[ $str1 = $str2 ]]