1.#!/bin/bash
shebang 可以自定义 比如 #!/bin/bash +x 就会打印出执行日志
linux中 0 代表null echo –e “1 2 3” 会转义其中的 ,生成3行数据 $! 保存着最近一个后台进程的PID $? 是最后一个命令的执行状态 0或1 (如果函数有return整数,那拿到的就是整数) $# 传递给脚本的参数个数 $$ 当前shell进程的ID sleep 1 单位秒,不需要加括号。 Wait 要想等所有子进程结束之后 再终止脚本,就得使用wait命令。 touch –d 可以造假 grep “^l” 可以过滤出软连接文件,^表示以xx起始的字符串。 echo 'Text through stdin' | cat – file.txt 这里的-是echo输出的作为管道后的stdin
2.命令序列界定
在Bash中,每个命令或是命令序列是通过使用分号或换行符来分隔的。
要么换行要么加分号;比如: $ cmd1 ; cmd2
它等同于: $ cmd1
$ cmd2
3.printf
- %s、%c、%d和%f都是格式替换符;
- %-5s指明了一个格式为左对齐且宽度为5的字符串替换(-表示左对齐)。如果不用-指定对 齐方式,字符串就采用右对齐形式。
- 宽度指定了保留给某个变量的字符数。对Name而言,保留 宽度是10。因此,任何Name字段的内容都会被显示在10字符宽的保留区域内,如果内容不足10 个字符,余下的则以空格符填充。
- 对于浮点数,可以使用其他参数对小数部分进行舍入。 对于Mark字段,将其格式化为%-4.2f,其中.2指定保留2个小数位。
4.赋值与相等
注意,var = value不同于var=value。把var=value写成var = value是一个常见的错误, 但前者是赋值操作,后者则是相等操作。
5.export
export PATH="$PATH:/home/user/bin" 也可以使用 $ PATH="$PATH:/home/user/bin" $ export PATH 导出函数 export -f fname
6. 字符串长度
length=${#var}
7.数学运算
普通的变量赋值方法定义数值,这时,它会被存储为字符串。
定义 no1=4; no2=5;
Let
变量前不需要加$符号,运算符前后也不需要加空格
let result=no1+no2 echo $result
$[]
在[]中也可以使用$前缀,也可以不用$前缀;但是运算符前后需要加空格
result=$[ no1 + no2 ] result=$[ $no1 + 5 ]
$(( ))
同上; 可以加$,也可以不加;运算符号前后需要空格
result=$(( no1 + 50 )) result=$(( $no1 + 50 ))
Expr
变量前必须加$,运算符号前后需要空格
result=`expr 3 + 4` result=$(expr $no1 + 5)
Bc
高级运算,看demo是需要用echo 和管道符参与运算;有的linux不支持
no=54; result=`echo "$no * 1.5" | bc` echo $result 81.0 echo "scale=2;3/8" | bc 0.37 scale设置小数精度 no=100 echo "obase=2; $no" | bc 输出1100100 no=1100100 echo "obase=10;ibase=2;$no" | bc 输出100 Obase和ibase代表输出进制和输入进制 计算平方以及平方根 echo "sqrt(100)" | bc echo "10^10" | bc
8.文件描述符及重定向
0 —— stdin(标准输入)。 1 —— stdout(标准输出)。 2 —— stderr(标准错误)。 cmd >stderr.txt 正常写入文件 cmd 2>stderr.txt 1>stdout.txt 不同日志追加到不同文件 cmd 2>&1 output.txt 2和1追加到一个文件 cmd &> output.txt 2和1追加到一个文件
文件黑洞、垃圾桶 /dev/null
9.tee
执行命令的时候,顺便copy一份为本地文件;tee –a 是追加,默认是覆盖 cat a* | tee out.txt | cat –n cat a* | tee –a out.txt | cat -n
10.文件描述符
文件描述符类似java中的文件引用(我自己觉得) exec 3<input.txt #引用 cat<&3 #读取
截断模式
$ exec 4>output.txt $ echo newline >&4 $ cat output.tx
追加模式
$ exec 5>>input.txt $ echo appended line >&5 $ cat input.txt newline appended line
11.数组
定义
array_var=(1 2 3 4 5 6) #这些值将会存储在以0为起始索引的连续位置上 另外,还可以将数组定义成一组“索引-值”: array_var[0]="test1" array_var[1]="test2" 。。。。
使用
echo ${array_var[0]} echo ${array_var[$var]} #变量 echo ${array_var[*]} 打印所有 echo ${array_var[@]} 打印所有 echo ${#array_var[*]} 打印数组length
12.关联数组(hashmap)
定义
$ declare -A ass_array
使用
ass_array=([index1]=val1 [index2]=val2) ass_array[index1]=val1 ass_array'index2]=val2
Keys收集map的keys
echo ${!array_var[*]} 数组前用!号 echo ${!array_var[@]} 数组前用!号
get获取value值
====== echo ${array_var[key]}
13.别名
alias new_command='command sequence' 不用别名,用原始命令 command 用途:rm 改为先扔到垃圾桶,在rm
14,.时间日期操作
纪元时间(单位秒) date +%s 1290047248 date --date "Thu Nov 18 08:07:21 IST 2010" +%s 1290047841 参数 Date “+ 参数1 参数2” date "+%d %B %Y" 20 May 2010
15.Time
Time sh脚本路径
得到执行脚本所花 费的时间
16.脚本调试
bash -x script.sh 使用set -x和set +x对脚本进行部分调试 for i in {1..6}; do set –x echo $i set +x done echo "Script executed" set –x:在执行时显示参数和命令。 set +x:禁止调试。 set –v:当命令进行读取时显示输入。 set +v:禁止打印输入。
#!/bin/bash –xv 调试脚本直接在脚本内写shebang
17.函数
function fname() { statements; } 或者: fname() { statements; } 可以不要function关键字; 函数定义不和java一样,还需要定义函数参数,直接传入用$1,$2接受。 调用函数 Fname 无参调用 fname arg1 arg2 含参调用 函数内使用参数 $@ 所有参数 $* 所有参数(这个用的少) $0 所有参数 cmd; echo $?; $?是上一步的执行结果0代表成功
函数返回值
sum(){ res=$[ $1 + $2 ] echo "$res" }
the_sum=$(sum 5 6)
echo "the_sum=${the_sum}"
输出the_sum=11
- 使用echo可以返回参数,返回多个参数用全局变量来接吧;
- Return 只能返回数值,需要用$?来接收;例子如下:
sum(){ res=$[ $1 + $2 ] return 100 } the_sum=$(sum 5 6) echo "the_sum=$?"
函数的跨脚本调用
场景:和java类似,有些通用的工具类进行封装后在别的地方就可以调用了。
Fun.sh内容:
sum(){ res=$[ $1 + $2 ] echo "$res" }
Test.sh脚本中调用sum
#!/bin/bash source ./fun.sh val=$(sum 4 3) echo "val="${val}
18.执行命令保留换行符
假设我们使用子shell或反引用的方法将命令的输出读入一个变量中,可以将它放入双引号 中,以保留空格和换行符( )。
$ cat text.txt 1 2 3 $ out=$(cat text.txt) $ echo $out 1 2 3
理论上换行符没了;但是我试下面的命令(加双引号)没有效果
$ out="$(cat tex.txt)" $ echo$out 1 2 3
19.Read
一般情况:有当回车键按下的时候,才标志着输入完毕 read -n 2 var #读取2个字符结束 read -s var #用无回显的方式读取密码 read -p "Enter input:" var #显示提示信息 read -t 2 var #在2秒内将键入的字符串读入变量var read -d ":" var #自定义结束符号 hello: #var 被设置为 hello
20. 运行命令直至执行成功
repeat() { while true do $@ && return done }
主要就是$@ && return $@读取输入参数,&& return 代表执行成功就返回。
21. 字段分隔符
IFS是存储定界符的环境变量。它是当前 shell环境使用的默认定界字符串。
IFS的默认值为空白字符(换行符、制表符或者空格)。
读取csv文件:
data="name,sex,rollno,location"
我们可以使用IFS读取变量中的每一个条目。
oldIFS=$IFS #将默认分隔符备份 IFS=, now, #修改默认分隔符 for item in $data; do echo Item: $item done IFS=$oldIFS #还原默认分隔符 输出如下: Item: name Item: sex Item: rollno Item: location
22.循环
echo {1..50}能够生成一个从1~50的数字列表。echo {a..z}或{A..Z}或{a..h}可以生
成字母列表
For循环
for var in list; do commands; #使用变量$var done循环 java 风格也可以 for((i=0;i<10;i++)) { commands; #使用变量$i }
While循环
while condition do commands; done
until循环
现在的语言里很少见until了,以前汇编语言里有。
x=0; until [ $x -eq 9 ]; #条件是[$x -eq 9 ] do let x++; echo $x; done
23.if条件控制
if condition; then commands; else if condition; then commands; else commands; fi
逻辑运算符判断(相当于if的简化版)
[ condition ] && action; # 如果condition为真,则执行action;
[ condition ] || action; # 如果condition为假,则执行action。
24.运算比较
一定要注意在[或]与操作数之间有一个空格。如果 忘记了这个空格,脚本就会报错
[ $var -eq 0 ] #当 $var 等于 0 时,返回真 -gt:大于。 -lt:小于。 -ge:大于或等于。 -le:小于或等于。 多个条件 [ $var1 -ne 0 -a $var2 -gt 2 ] #使用逻辑与-a [ $var1 -ne 0 -o var2 -gt 2 ] #逻辑或 –o 或者 [ 5 = 5 ] && [ 3 = 3 ]
25.字符串比较
使用字符串比较时,最好用双中括号,因为有时候采用单个中括号会产生错误
[[ $str1 = $str2 ]] #单等号 或者 [[ $str1 == $str2 ]] #双等号 双等号和单等号效果一样 [[ $str1 != $str2 ]] #不等
非空校验
[[ -z $str1 ]]:如果str1包含的是空字符串,则返回真。 [[ -n $str1 ]]:如果str1包含的是非空字符串,则返回真。 if [[ -n $str1 ]] && [[ -z $str2 ]] ; #多条件判断 then commands; fi
test 可以替换[[]]和[],这样做是避免使用太多中括号。
[]内布尔值无法赋值给变量的问题
`[ 5 = 3 ] ; echo $?` `[ 5 = 3 ] && echo $?` 不能直接用var=[ 5 = 3 ]赋值,只能这样[ 5 = 1 ] ; v=$?; echo $v