Bash语言总结

来源:互联网 发布:linux find mtime时间 编辑:程序博客网 时间:2024/06/07 22:15

循环语法妙用

输出读取文件的的每一行

while read line  && [[ $word != end ]];do    echo $linedone < /path/file;

for循环可以用{}代替do,done,类似C语法的形式

#!/bin/bashfor i in seq 10{    echo $i}

此外还可以通过while 与 read命令获取,PIPE管道的标准输入

#!/bin/bashwhile read line;do    echo $linedone  ##示例: ls | ./test.sh

test命令

test命令基本等价于 []
用法示例:

if test -e ./file;then   echo truefi

表达式相关

获取表达式的值 : $(())
示例:

echo $((6%3))输出   0

也可以进行赋值

$((var=6%3))echo $var输出var的值

数组相关

数组定义

arr=(`ls ./`)arr=(1 2 3 4)

数组遍历

arr=(1 2 3 4)for i in ${arr[*]};do    echo $idone

数组的截取

arr=( one two three four five five )echo ${arr[@]:1:3} #1是数组要截取的起始位置,3是截取数组的长度echo ${arr[@]#f*r} #删除匹配到的f*r  懒惰模式echo ${arr[@]##t*e} #删除匹配到的t*e 贪婪模式unset arr[3] #删除指定的元素

其它的截取、替换、删除不在赘述,详情参照字符串,使用方法与字符串类似,只是作用的元素不一样。

if条件判断的注意事项

[]变量与[或者]需要空格隔开
test命令与[]的执行可以说基本一致,只是执行的方法
[[]]遵循逻辑短路,[]不遵循逻辑短路
[[]]支持 && || > < 逻辑判断符
-a, -o 表示逻辑
提示:
[]中只能使用-a或者-o进行与逻辑判断,[[]]支持&&操作符
[]或者[[]]中使用问题:
1.判断条件值需要用空格与[隔开
2.判断条件需要两个值需要与逻辑判断符用空格隔开123 == 123,否则会一直返回true
3.if判断的用法不仅限于 [[]] 判断

if echo "$word" | grep "123"thenecho "123"elseecho "not found"fi

另一种方式的if else,这种方式使代码更加简洁,但是多条命令还是推荐之前的写法

#!/bin/basha=abcb=efgc=jlk[[ -z $c ]] && echo $b || echo $a #输出abc 返回false

case条件判断

case条件判断中,无需break,跳出默认不会贯穿执行

case $a in a|A)    echo "A|a";;b|B)    echo "B|b";;esac

字符串

实现字符串的拼接
1.str=str1{str2}
2.str=”str1str2”

注意以下涉及位置的是从1开始计算
获取匹配字符串的长度
方式1:

$str=abcdefgecho `expr match "$str" '$substr'`#$substr是一个正则表达式的字符串  

方式2:

$str=abcdecho `expr "$str" : '$substr'`#$substr是一个正则表达式的字符串

获取子串在字符串这的位置

str=cdcasdsabecho `expr index "$str" dc` #1 输出1 是因为c最新被匹配到

获取子串

echo `expr subtr "$str" 2 4` #截取起始位置是2长度为4的字符串

注意以下涉及位置是从0开始计算
获取子串

${string:position} #获取子串从position位置开始${string:position:length} #获取子串从position位置开始,长度为length的子串

同样也可以采取这样的方式获取参数

echo ${*:2} #输出参数中 第二个参数起始包括第二个参数的所有参数echo ${@:2} #同上echo ${*:2:3} #获取参数中,第二参数起,包括第二个参数的三个参数

其它

以下情况针对变量也可以。
删除字符串,从前开始

${str#substr} #返回删除substr后的字符串  懒惰模式${str##substr} #尽可能多的删除掉匹配的substr  类似于正则中的贪婪模式

删除字符串从后开始

${string%sub}  #从字符串末尾位置开始删除sub子串 懒惰模式${string%%sub} #从字符串末尾位置开始尽可能多的删除sub子串  贪婪模式

字符串替换

${str/substr/rep} 替换查找到的第一个substr为rep${str//substr/rep}替换查找到所有的substr为rep${str/#substr/rep}替换查找从前往后查找的第一个substr为rep${str/%substr/rep}替换查找从后往前的第一个substr为rep

函数

函数中获取参数,注意函数值的1,1是不一样的,函数中的1使1变量

func (){    echo $1}

获取命令的执行结果

chars=$(cat /etc/password)

chars 变量的值就是执行car /etc/password的结果

可以进行命令拼接

#!/bin/bashfor file in $(ls $1.log.* );do #查找当前目录中匹配 $1.log.*  的日志文件    echo $filedone

脚本中获取Linux信号

#!/bin/bashtrap 'echo "exit now" ' 2 3 15 19 #当接收到 CTRL+C 或者退出  命令时直接输出trap '' 2 #直接忽略CTR+C信号,当在命令行狂按CTR+C时,没有被处理trap 2 #按默认方式去处理testFunc(){    echo "test"}   ##也可以在shell脚本内调用函数:trap testFunc 2

需要注意的是 SIGKILL,SIGTERM 信号机制,当接收到此命令时 shell脚本不能做任何处理
信号机制的含义详见附录表.

参数替换

${parameter-default}${parameter:-default}差异

If parameter not set, use default.

asdasd=456var1=${www:-asdasd}echo var1 #输出456unset var1var1=var1=${www:asdasd}echo $var1 # 没有输出信息

当var1 声明,但是值为null时,${parameter:default}不会输出值
赋值时需要注意

echo ${var=abc} #输出var的值为abcecho ${var=xyz}#输出var的值为abc,var的值已经赋值不会改变,也就是说对于已经赋值的变量不会改变其值

${parameter=default}, ${parameter:=default}

If parameter not set, set it to default.

${parameter+alt_value},${parameter:+alt_value}

If parameter set, use alt_value, else use null string.

${parameter?err_msg}, ${parameter:?err_msg}

If parameter set, use it, else print err_msg and abort the script with an exit status of 1.

输入输出重定向

输出、输入重定向

#错误输出重定向ls 2 > file #错误输出与标准输出重定向,将错误输出当做标准输出ls > file 2>&1#错误输出与标准输出重定向ls &> file#标准输出当做错误输出ls 2>file 1>&2#输入重定向ls < file

注意事项

1.给变量赋值时 =两边不要存在空格,否则会当成命令进行执行
2.?03.@是所有的参数列表,#为参数的个数  
4.
!是该执行脚本的PID
5.脚本中单引号不可包含变量,双引号字符串换可以
6.多个语句写在同一行需要用 ;进行分割
7. 中间的command可以赋值于变量,执行后的输出
8. command &> filename 重定向输出错误与标准输出
9. 在脚本中需要使用设置别名时,在脚本前先需执行,shopt -s expand_aliases

技巧

1.赋值字符串也可以不要引号

var1=123\ waterecho $var1 #123 water

补充我们也可以多行输入

echo 123\456#123456 输出一行

2.赋值ASCII码值
3.输出bash的版本号

echo $BASH_VERSION

4.输出脚本的执行栈

sh -x test.sh #检测脚本的执行栈错误

5.检测shell脚本的语法错误

sh -n test.sh #检测test.sh是否存在语法错误

6.脚本内设置$1...$n参数

#!/bin/bashset -- "First param" "Second param"

7.声明变量的类型

#!/bin/bashdeclare -i  var1 #声明一个整形变量declare -f function_name #声明一个函数declare -a array1 #声明一个数组declare -r var1=1 #声明一个只读变量,如果被重新赋值,直接报错export NAME="lzx"  #定义一个全局变量,永久生效,针对单一用户,在定义全局变量之前一定要,了解相关的环境变量,避免覆盖

8.获取变量名称,从变量的名称获取变量的值

#!/bin/bashvar1=123var2=234${var!var*} #变量var的值为 var1 var2for i in $var;do    echo ${i} #123 234done    

9.将循环中生成的变量

#!/bin/bashvar=`for i in $(seq 10)doecho $idone`#var的值为 1 2 ... 10

需要注意:shell脚本默认定义的变量是global类型,从定义开始到脚本结束,或者被显示删除的,
local定义的变量为局部变量,与global同名的变量会被替代,作用域为声明的函数内(只在函数内声明)。

#!/bin/bashfunc1(){ loacal a=10}

10.shift用法
遍历输入参数

for in $@;do echo $1 shiftdone

10.getopts 获取参数
在编写shell脚本的时候我们经常会遇到简称的采用, -a 123 -b 456
两个需要关注的变量
$OPTARG 当前选项的值
$OPTIND当前选项索引值,从1开始计算
第一个冒号表示忽略参数错误,参数选项不正确默认情况会报错,
选项后的冒号表示,该选项需要参数值

while getopts ":a:b:c" optdo    case $opt in        a)            echo $OPTARG        b)            echo $OPTARG    esac            done

11.引用其他文件
方便业务的模块化
source, .命令都支持传参

. "filename"source "filename" 123 456

12.可以给函数使用重定向,或者管道进行输入和输出,管道需要嵌套block,

func(){} < /tmp/datafunc(){    {        echo $*    } | tr a b  } 

13.函数的递归调用

斐波那契数列 递归调用,非常慢。
摘自asb-guide

#!/bin/bashMAXTERM=15 # Number of terms (+1) to generate.MINIDX=2 # If idx is less than 2, then Fibo(idx) = idx.Fibonacci (){ idx=$1 # Doesn't need to be local. Why not? if [ "$idx" -lt "$MINIDX" ] then echo "$idx" # First two terms are 0 1 ... see above. else (( --idx )) # j-1 term1=$( Fibonacci $idx ) # Fibo(j-1) (( --idx )) # j-2 term2=$( Fibonacci $idx ) # Fibo(j-2) echo $(( term1 + term2 )) fi # An ugly, ugly kludge. # The more elegant implementation of recursive fibo in C #+ is a straightforward translation of the algorithm in lines 7 - 10.}for i in $(seq 0 $MAXTERM)do # Calculate $MAXTERM+1 terms. FIBO=$(Fibonacci $i) echo -n "$FIBO "done# 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610# Takes a while, doesn't it? Recursion in a script is slow.echoexit 0

14.声明函数的另一种方式
需要注意的是,for循环遍历这样的数组时,不能被正常的

#!/bin/basharr=( [0]="one two" [1]="three four" [3]="five" )echo ${arr[0]}#one two

15.根据变量值获取另一个变量值

$var=a$a=456echo "$$var" #456

附录表:

文件相关
-e filename 如果filename存在则为真
-r filename 如果文件存在且可读为真
-w filename 如果文件存在且可写为真
-x filename 如果文件存在可写为真
-d filename 如果文件存在且为目录为真
-f filename 如果文件存在且为普通文件为真

字符串相关
==,!= 判断字符串相等或者不等
-z 判断字符串长度为0则为真
-n 判断字符串长度不为0则为真

全局变量
$UID只有当值为0时,执行脚本的权限为root权限
$PPID获得进程的父进程的ID号
$IFS数组分割的变量,改变其值会影响$@, $*参数的值
$0当前执行脚本的名称,注意使用sh test.sh会输出test.sh 如果使用路径执行./test.sh会输出./test.sh
$* 与 $@类似,获取输入参数
$$改脚本执行的PID
$?获取函数的返回值,命令最后一个执行的结果
$#获取脚本的参数的个数
$!获取最后一个运行在后台的进程ID

全局函数
$RANDOM内部函数,生成一个0-32767的随机数,是一个函数并不是常量

Linux常用信号机制表
SIGHUP 1 终端的挂断或进程的死亡
SIGINT 2 来自键盘的中断信号^+C
SIGQUIT 3 来自键盘的退出信号^+\
SIGKILL 9 杀死进程的信号
SIGTERM 15 终止信号 无法被trap捕获
SIGALRM 14 收到alarm信号

Bash 4以上新特性

associative array

example

arr[index1]="value"arr[index2]="value"

case结构体
case结构体当中的;;是默认不贯穿执行的
;;& 表示执行到下个case语句,通过case条件判断
;& 不管case条件是否通过都执行下个语句,不推荐使用这个符号,破坏了case语言的结构

test_func(){    case "$1" in        1) echo "number one";;&        2) echo "number two";;        3) echo "number three";&        4) echo "number four";;}test_func 1#输出number one不符合下个的case条件test_func 3#输出number three number four

declare 支持-l (lowercase) -c (capitalize)

表达式支持增量设置
{40..60..2}

**操作符 可以递归的遍历文件
前提条件是在脚本开始处

shopt -s globstarfor filename in **do     echo $filenamedone    exit

内置的错误
command_not_found_handle
在bash中调用一个没有定义的命令 会抛出对应的异常
example

command_not_found_handle (){  echo "The following command is not valid: \""$1\""" echo "With the following argument(s): \""$2\"" \""$3\""" # $4, $5 ...}
原创粉丝点击