bash脚本(一)

什么是脚本,其实脚本是有若干个命令串起来执行的命令行,如下图。命令行一行有255个字符数的限制,所以一般长些的脚本都写在文件中。

  1. [[email protected] ~]# date;uname -a;pwd
  2. Thu Dec 4 17:29:52 CST 2014    date命令显示
  3. Linux localhost.localdomain 2.6.32-504.el6.x86_64 #1 SMP Wed Oct 15 04:27:16 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux    uname -a命令显示
  4. /root    pwd命令显示
  1. [[email protected] ~]# cat test.sh
  2. #!/bin/bash      Shebang这个符号通常在Unix系统的脚本中第一行开头中写到,它指明了执行这个脚本文件的解释程序
  3. A=test test赋值给A
  4. echo "$A"        双引号是弱引用,显示A变量
  5. echo ‘$A‘      单引号是强引用,所以显示的是$A
  6. [[email protected] ~]# bash test.sh bash是命令,test.sh相当于参数
  7. test
  8. $A
  9. [[email protected] ~]# A=`pwd`         命令引用,把命令结果输出
  10. [[email protected] ~]# echo $A
  11. /root
  1. [[email protected] ~]# ./test.sh    shell能够提供一些内部命令,并且能通过PATH环境变量找到外部命令;把命令提交给内核启动为进程,由于被当成命令来执行没有执行权限,所有被拒绝
  2. -bash: ./test.sh: Permission denied
  3. [[email protected] ~]# ll test.sh
  4. -rw-r--r-- 1 root root 39 Dec 5 10:49 test.sh
  5. [[email protected] ~]# chmod a+x test.sh
  6. [[email protected] ~]# ll test.sh
  7. -rwxr-xr-x 1 root root 39 Dec 5 10:49 test.sh
  8. [[email protected] ~]# ./test.sh    bash读取到了第一行的shebang,就调用bash
  9. test
  10. $A

变量

局部变量:函数调用的整个生命周期

如:local VAR=VALUE

本地变量:整个脚本,在脚本的函数中也可调用,也可修改

declare -a:定义数组

declare -i:定义整数

declare -r:定义只读变量,不能别unset

环境变量:定义工作目录,提示字符,执行命令搜索路径等
        1、全局环境变量(范围全局)

export VAR_NAME=VALUE

declare -x VAR_NAME=VALUE

env,printenv

2、局部环境变量(范围局部)

set:

位置参数变量:$0(获取程序名),$1(获取第一个参数),$2,$3,$4,....$9,${10}

特殊变量:[email protected](取得所有参数),$*(取得所有参数),$#(取得参数个数)

[email protected]和$*的区别

  1. #!/bin/bash
  2. count1=1
  3. for i in "$*"; do
  4. echo "A$count1 = $*"
  5. count1=$[ $count1 + 1 ]
  6. done
  7. count2=1
  8. for j in "[email protected]"; do
  9. echo "B$count2 = [email protected]"
  10. count2=$[ $count2 + 1 ]
  11. done
  12. [[email protected] ~]# bash test.sh 1 2
  13. A1 = 1 2
  14. B1 = 1 2
  15. B2 = 1 2

4种算术运算

  1. [[email protected] ~]# A=1
  2. [[email protected] ~]# echo $[ $A+1 ] 1、第一种算术运算
  3. 3
  4. [[email protected] ~]# echo $[$A+1]
  5. 3
  6. [[email protected] ~]# echo $(($A+1)) 2、第二种算术运算
  7. 3
  8. [[email protected] ~]# let A++      3、自增相当于let A=$A+1
  9. [[email protected] ~]# echo $(( $A+1 ))
  10. 3
  11. [[email protected] ~]# echo $( expr $A+1) 4、必须在+号两边那空格
  12. 2+1
  13. [[email protected] ~]# echo $( expr $A + 1)
  14. 3

输入输出重定向

0    STDIN        标准输入    <或<<

1    STDOUT    标准输出     >或>>

2    STDERR     标准错误     2>或2>>

  1. [[email protected] ~]# ls /etc/fstab /1111 2> test2 1> test3 如不重定向默认是在显示器上输出
  2. [[email protected] ~]# cat test2 将STDERR错误重定向到test2
  3. ls: cannot access /1111: No such file or directory
  4. [[email protected] ~]# cat test3 将STDOUT重定向到test3
  5. /etc/fstab
  6. [[email protected] ~]# ls /etc/fstab /1111 &> test4 把正确的和错误的都重定向到test4
  7. [[email protected] ~]# cat test4
  8. ls: cannot access /1111: No such file or directory
  9. /etc/fstab

永久重定向

  1. bash test.sh
  2. [email protected] ~]# cat test.sh 
  3. #!/bin/bash
  4. exec 2>testerror
  5. exec 1>testout
  6. echow "error"
  7. echo "aaa"
  8. lss /tmp
  9. ls /tmp
  10. [[email protected] ~]# cat testout 
  11. aaa
  12. test
  13. [[email protected] ~]# cat testerror 
  14. test.sh: line 5: echow: command not found
  15. test.sh: line 7: lss: command not found

创建自己的重定向

在shell中最多可以有9个打开的文件描述符。其他6个文件描述符会从3-8,并且可以当做输入或输出重定向都行。

  1. #!/bin/bash
  2. exec 3>test3out
  3. echo "11"
  4. echo "22"
  5. echo "33" >&3 >&重定向到 <&输入重定向
  6. [[email protected] test]# bash test.sh
  7. 11
  8. 22
  9. [[email protected] test]# cat test3out
  10. 33

退出状态码

当命令执行完毕会有一个退出状态码,可以通过$?查看,状态码的范围是0-255,如返回值是300,状态码会显示44(256的余数),在比较测试中命令状态码0表示true,非0为false

  1. [[email protected] ~]# pwdd;echo $? 命令执行失败后状态码为127
  2. -bash: pwdd: command not found
  3. 127
  4. [[email protected] ~]# pwd;echo $?   命令执行成功,后显示为0
  5. /root
  6. 0
  7. [[email protected] ~]# cat test.sh 可以通过exit来定义退出状态码
  8. #!/bin/bash
  9. exit 300
  10. [[email protected] ~]# echo $?
  11. 44
  1. [[email protected] ~]# cat > test6 << EOF 在屏幕输出后输入到test6
  2. > first
  3. > second
  4. > third
  5. > EOF
  6. [[email protected] ~]# cat test6
  7. first
  8. second
  9. third

测试相关

测试方式有3种

1、test EXPRESSION

2、[ EXPRESSION ]

3、[[ EXPRESSION ]]

数值测试,两边需要空格

n1 -eq n2 n1是否等于n2

n1 -ge n2 n1是否大于等于n2

n1 -gt n2         n1是否大于n2

n1 -le n2         n1是否小于等于n2

n1 -lt n2         n1是否小于n2

n1 -ne n2 n1是否不等于n2

  1. [[email protected] ~]# [ 1 -ne 0 ];echo $?     1不等于0为真
  2. 0
  3. [[email protected] ~]# [ 1 -eq 0 ];echo $?    1等于0为假
  4. 1
  5. [[email protected] ~]# [[ 10 -eq 9 ]];echo $?    10等于9为假
  6. 1
  7. [[email protected] ~]# [[ 10 -ne 9 ]];echo $?    10不等于9为真
  8. 0
  9. [[email protected] ~]# test 1 -ne 0;echo $?     1不等于0为真
  10. 0
  11. [[email protected] ~]# test 1 -eq 0;echo $?    1等于0为假
  12. 1

字符测试

str1 == str2     str1是否和str2相同

str1 != str2       str1是否和str2不同

str1 < str2        str1是否比str2小

str1 > str2        str1是否比str2大

-n str1              判断str1是否不空;不空则为真,空则为假;

-z str1               判断str1是否为空;空则为真,不空则假;

  1. [[email protected] ~]# [[ a > b ]];echo $? a大于b为假
  2. 1
  3. [[email protected] ~]# [[ a < b ]];echo $?    a小于b为真
  4. 0
  5. [[email protected] ~]# [ a < b ];echo $? 在字符测试中单中括号是不生效的
  6. 0
  7. [[email protected] ~]# [ a > b ];echo $?
  8. 0
  9. [[email protected] ~]# test a > b;echo $?
  10. 0
  11. [[email protected] ~]# test a < b;echo $?
  12. 0
  13. [[email protected] ~]# test a \< b;echo $? 字符比较大于等于号必须要加反斜杠转义
  14. 0
  15. [[email protected] ~]# test a \> b;echo $?
  16. 1

"$A" =~ PATTERN 如果变量A中保存的字符串能被PATTERN所匹配;即为真;否则为假

  1. [[email protected] ~]# echo $A
  2. blue
  3. [[email protected] ~]# [[ "$A" =~ b ]];echo $?
  4. 0
  5. [[email protected] ~]# [[ "$A" =~ a ]];echo $?
  6. 1
  7. [[email protected] ~]# [[ "$A" =~ a* ]];echo $?
  8. 0
  9. [[email protected] ~]# [[ "$A" =~ . ]];echo $?
  10. 0
  11. [[email protected] ~]# [[ "$A" =~ * ]];echo $?
  12. 2

文件测试

-d file:目录是否存在

-e file:是否存在,存在则为真

-a $file: 同上;弃用;

-f file:是否存在且为普通文件

-h file:是否存在且为符号链接文件

-L $file:同上

-b file:是否存在且为块设备文件

-c file:是否存在且为字符设备文件

-p file:是否存在且管道文件

-S file:是否存在且为套接字文件

-s file:是否存且是否为非空文件

  1. [[email protected] ~]# [[ -b /dev/sda ]];echo $?
  2. 0
  3. [[email protected] ~]# [[ -b /dev/sd ]];echo $?
  4. 1

-r file:是否存在且当前用户是否拥有读权限

-w file:是否存在且当前用户是否拥有写全权限

-x file:是否存在且当前用户是否拥有执行权限

-O file:是否存在且当前用户所有

-G file:是否存用户默认组相同

  1. [[email protected] ~]$ [[ -w /etc/passwd ]];echo $? centos用户对/etc/passwd文件不能写
  2. 1
  3. [[email protected] ~]$ [[ -w /etc/ ]];echo $? 也可以对目录测试
  4. 1
  5. [[email protected] ~]$ [[ -w /tmp ]];echo $?
  6. 0
  7. [[email protected] ~]$ touch /tmp/centos
  8. [[email protected] ~]$ ll /tmp/centos
  9. -rw-rw-r-- 1 centos centos 0 Dec 5 14:37 /tmp/centos
  10. [[email protected] ~]$ [[ -w /tmp/centos ]];echo $? 可以写显示为0
  11. 0

-N file:文件自从上一次被读取之后,是否被修改过

file1 -nt file2:文件file1是否比文件file2新

file1 -ot file2:文件file1是否比文件file2旧

file1 -ef file2:file1和file2是否为同一个文件的硬链接

  1. [[email protected] ~]$ ll /etc/fstab
  2. -rw-r--r--. 1 root root 921 Nov 28 08:29 /etc/fstab
  3. [[email protected] ~]$ ll /tmp/test.sh
  4. -rw-r--r-- 1 root root 339 Dec 5 10:49 /tmp/test.sh
  5. [[email protected] ~]$ [[ /etc/fstab -nt /tmp/test.sh ]];echo $?
  6. 1
  7. [[email protected] ~]$ [[ /etc/fstab -ot /tmp/test.sh ]];echo $? fstab比test旧
  8. 0

组合测试

或 -o:[ EXPRESSION -o EXPRESSION ]

与 -a:[ EXPRESSION -a EXPRESSION ]

非 !:[ ! EXPRESSION ]

  1. [[email protected] ~]# [ -z "" -a -f /etc/fstab ];echo $? 2者都满足则为真
  2. 0
  3. [[email protected] ~]# [ -n "" -a -f /etc/fstab ];echo $?
  4. 1
  1. [[email protected] ~]# [ 1 -gt 2 ];echo $? 没加!状态码非0
  2. 1
  3. [[email protected] ~]# [ ! 1 -gt 2 ];echo $? 加了!状态码为0
  4. 0

与:COMMAND1 && COMMAND2

或:COMMAND1 || COMMAND2

非:! COMMAND

  1. 在/tmp/下创建了4个文件,以下真为状态码为0
  2. 真 执行 && 真 执行 && 真 执行 && 真 执行
  3. [[email protected] ~]# ls /tmp/test1 && ls /tmp/test2 && ls /tmp/test3 && ls /tmp/test4
  4. /tmp/test1
  5. /tmp/test2
  6. /tmp/test3
  7. /tmp/test4
  8. 真 执行 && 真 执行 || 不执行 && 真执行
  9. [[email protected] ~]# ls /tmp/test1 && ls /tmp/test2 || ls /tmp/test3 && ls /tmp/test4
  10. /tmp/test1
  11. /tmp/test2
  12. /tmp/test4
  13. 真 执行 || 不执行 || 不执行 && 执行
  14. [[email protected] ~]# ls /tmp/test1 || ls /tmp/test2 || ls /tmp/test3 && ls /tmp/test4
  15. /tmp/test1
  16. /tmp/test4
  17. 假 返回错误 || 真 执行 || 不执行 && 执行
  18. [[email protected] ~]# lss /tmp/test1 || ls /tmp/test2 || ls /tmp/test3 && ls /tmp/test4
  19. -bash: lss: command not found
  20. /tmp/test2
  21. /tmp/test4
  1. [[email protected] ~]# ls /tmp/test1 &> /dev/null;echo $? 命令执行成功状态码为0,&> /dev/null 为把错误和正常输出全部丢弃
  2. 0
  3. [[email protected] ~]# ! ls /tmp/test1 &> /dev/null;echo $? 加了!状态码为非0
  4. 1

交互式相关

  1. [[email protected] ~]# read -t 3 -p "Enter your menu:" menu -t为3秒后不等待输入,直接进入下一步 -p为显示输入提示,
  2. Enter your menu:                                    menu为输入的参数赋值给menu

-s 选项是隐藏方式读取(如输入密码的时候)

可以和[ -z "$VAR" ] && VAR=VALUE结合使用,如3秒后为输入,赋给它默认的值

字符串操作

字符串切片${var:offset:lenth}

  1. [[email protected] ~]# A=test;echo ${A:2:2} 取3,4两个字符
  2. st

取字符串最后的几个字符:${var: -lenth},冒号后面有空格

  1. [[email protected] ~]# A=test;echo ${A: -2}
  2. st

取子串

${var#*word}:从左开始删除到第一个word字符的数据(包含word字符)

  1. [[email protected] ~]# A=www.sina.com.cn;echo ${A#*.}
  2. sina.com.cn

${var##*word}:从左开始删除到最后一个word之间的数据(包含word字符)

  1. [[email protected] ~]# A=www.sina.com.cn;echo ${A##*.}
  2. cn

${var%word*}:从右开始删除到第一次出现word的数据(包含word字符)

  1. [[email protected] ~]# A=www.sina.com.cn;echo ${A%.*}
  2. www.sina.com

${var%%word*}:从右开始删除到最后一次出现word的数据(包含word字符)

  1. [[email protected] ~]# A=www.sina.com.cn;echo ${A%%.*}
  2. www

基于模式的查找替换,删除,可使用?, *元字符

查找替换

${var/pattern/substi}:替换第一次pattern匹配到的模式

  1. [[email protected] ~]# A="aaa bb cc aa";echo ${A/a*/AA}
  2. AA
  3. [[email protected] ~]# A="aaa bb cc aa";echo ${A/a?/AA}
  4. AAa bb cc aa

${var//patten/subst}:替换所有pattern匹配到的字符

  1. [[email protected] ~]# A="aaa bb cc aa";echo ${A//a?/AA}
  2. AAAAbb cc AA

${var/#pattern/subst}:以行首锚定方式替换以pattern开头的行,如能匹配则替换subst

  1. [[email protected] ~]# A="aaa bb cc aa";echo ${A/#a?/AA}
  2. AAa bb cc aa
  3. [[email protected] ~]# A="aaa bb cc aa";echo ${A/#b*/AA}
  4. aaa bb cc aa

${var/%pattern/subst}:以行尾锚定方式将pattern匹配至var,如能匹配替换subst

  1. [[email protected] ~]# A="aaa bb cc aa";echo ${A/%cc/AA}
  2. aaa bb cc aa
  3. [[email protected] ~]# A="aaa bb cc aa";echo ${A/%aa/AA}
  4. aaa bb cc AA

查找并删除

${var/pattern}:删除pattern匹配到的第一次出现

  1. [[email protected] ~]# A="aaa bb cc aa";echo ${A/b*}
  2. aaa
  3. [[email protected] ~]# A="aaa bb cc aa";echo ${A/b?}
  4. aaa cc aa

${var//pattern}: 删除pattern匹配到的所有出现

  1. [[email protected] ~]# A="aaa bb cc aa";echo ${A//a?}
  2. bb cc
  3. [[email protected] ~]# A="aaa bb cc aa";echo ${A//a*}

${var/#pattern}:删除以pattern开头字符

  1. [[email protected] ~]# A="aaa bb cc aa";echo ${A/#a?}
  2. a bb cc aa

${var/%pattern}:删除以行尾锚定pattern的字符

  1. [[email protected] ~]# A="aaa bb cc aa";echo ${A/%a?}
  2. aaa bb cc

字符串大小写转换

${var^^}:小写-->大写

  1. [[email protected] ~]# A="aa";echo ${A^^}
  2. AA

${var,,}:大写-->小写

  1. [[email protected] ~]# A="AA";echo ${A,,}
  2. aa

变量赋值

${var:-word}: 如果var为空或未设置,那么返回word;否则,则返回var中的值

  1. [[email protected] ~]# echo $A
  2. [[email protected] ~]# echo ${A:-test}
  3. test
  4. [[email protected] ~]# echo $A

${var:=word}:如果var为空或未设置,那么返回word,并且将word赋值给var;否则,返回var中的值

  1. [[email protected] ~]# echo $A
  2. [[email protected] ~]# echo ${A:=test}
  3. test
  4. [[email protected] ~]# echo $A
  5. test

${var:?err_info}:如果var为空或未设置,那么返回错误信息;否则,则返回var自身的值

  1. [[email protected] ~]# echo $A
  2. [[email protected] ~]# echo ${A:?test}
  3. -bash: A: test
  4. [[email protected] ~]# echo $A
  5. [[email protected] ~]# A=tset
  6. [[email protected] ~]# echo ${A:?111}
  7. tset

${var:+word}:如果var自身有正常数据,则返回word

  1. [[email protected] ~]# echo $A
  2. [[email protected] ~]# echo ${A:+test}
  3. [[email protected] ~]# echo $A
  4. [[email protected] ~]# A=AAAAA
  5. [[email protected] ~]# echo ${A:+test}
  6. test
  7. [[email protected] ~]# echo $A
  8. AAAAA
时间: 2024-10-12 09:42:28

bash脚本(一)的相关文章

Linux Bash脚本基本语法知识

写在前面:如果此文有幸被某位朋友看见并发现有错的地方,希望批评指正.如有不明白的地方,愿可一起探讨. 前提:读者能够基本使用一款文本编辑器以及了解文件的权限概念. 准备工作 在/home目录创建script文件用于保存所有的脚本程序: # mkdir /home/script # cd /home/script/ Bash脚本的基本输入输出 第一个bash脚本: # vim ./hello-world.sh 说明: "#!"是一个约定标记,它告诉系统这个脚本需要什么解释器来执行 作为可

Bash脚本之if、case、read和位置参数

在学会了基本的命令之后,我们就可以使用这些命令来进行编程了.在Linux中的编程称为shell脚本,是将命令进行结合形成的类似Windows中批处理的东西.在这个脚本中,可以有变量和结构体.每一个程序所拥有的程序执行过程,例如:顺序执行.选择执行和循环执行都可以在脚本中体现出来.下面就对shell脚本进行介绍. 首先,shell脚本编程是过程式编程语言,也就是说shell脚本强调接下来要执行的步骤,就好像是人在对shell说接下来要做什么,要明确的指出每一步的方法.然后shell还是脚本类语言,

从此编写 Bash 脚本不再难【转】

从此编写 Bash 脚本不再难 原创 Linux技术 2017-05-02 14:30 在这篇文章中,我们会介绍如何通过使用 bash-support vim 插件将 Vim 编辑器安装和配置 为一个编写 Bash 脚本的 IDE. -- Aaron Kili 本文导航 -什么是 bash-support.vim 插件? …… 05% -如何在 Linux 中安装 Bash-support 插件 …… 10% -如何在 Vim 编辑器中使用 Bash-support 插件 …… 17% -如何为

用Bash脚本将Linux普通用户添加为系统管理员

将Linux普通用户添加为系统管理员在Gnome或KDE这样强大与完善的桌面环境下是非常简单的事情,一般来说在用户设置的对话框里就直接有相应选项.不过,出于简洁与高效的风格,自己目前并未使用这些高端但吃内存的“重量级”桌面环境,使用的就是最基本的X视窗+Sawfish窗口管理器的组合.在这样的环境下进行用户管理,都是通过命令行来完成.如,使用useradd命令添加新用户.不过,由useradd命令添加的用户只具有普通使用者的权限,不具备系统管理的能力.这样一来,就给一些常见的操作带来不便,如,使

Linux应用环境实战10:Bash脚本编程语言中的美学与哲学(转)

阅读目录 一.一切皆是字符串 二.引用和元字符 三.字符串从哪里来.到哪里去 四.再加上一点点的定义,就可以推导出整个Bash脚本语言的语法了 五.输入输出重定向 六.Bash脚本语言的美学:大道至简 总结: 我承认,我再一次地当了标题党.但是不可否认,这一定是一篇精华随笔.在这一篇中,我将探讨Bash脚本语言中的美学与哲学. 这不是一篇Bash脚本编程的教程,但是却能让人更加深入地了解Bash脚本编程,更加快速地学习Bash脚本编程. 阅读这篇随笔,不需要你有Bash编程的经验,但一定要和我一

bash脚本编程之条件判断、条件测试

脚本编程: 编程面向过程有如下几种执行方式 顺序执行 选择执行:  如 if, case 循环执行:  如 for, while, until bash的变量类型: 本地变量 set VAR_NAME=value 设置变量赋值 如: set User=Centos unset VAR_NAME 撤消变量赋值 如: unset User=Centos ${VAR_NAME} 作用范围:当前shell进程: 局部变量 local VAR_NAME=value 设置变量赋值 unset VAR_NAM

回忆曾经写过的第一个Bash脚本

这盘文章,算是杂谈吧,想谈谈我对于Linux操作系统的灵魂之笔 Bash的理解. 据说Shell脚本有50种之多(陈皓老师的酷壳网上有一篇博文 http://coolshell.cn/articles/8619.html 提到),现在,用Linux调试大大小小程序,除了使用Makefile,偶尔用用CMakeList.txt, 更多程序是用bash 脚本来实现半自动化调试,就像在VS下面,每次修改重新编译一样,你总是 gcc 或者 g++,然后 ./test 运行,然后再看看有没有错,编译出错又

bash脚本编程之变量、变量类型、条件测试、算术运算、及特殊变量

一.学习目的 1.了解bash脚本的变量类型及变量的使用 2.了解bash中条件测试的种类及如何在bash中实现条件的判断 3.学会在bash中做算术运算 4.了解特殊变量的使用 二.学习内容 1). ①.bash的变量类型: 环境变量 .本地变量.局部变量.位置变量.特殊变量 环境变量: export VALUENAME = VALUE 作用领域是当前的shell进程及其子进程 本地变量: VALUENAME= VALUE 作用领域为整个bash的进程 局部变量:local VALUENAME

bash脚本的变量使用详解

变量的类型包括整数.字符串和数组,但在bash脚本编程中不需要指定类型就可以直接赋值,默认均为字符型,其参与运算会自动进行隐式类型转换. 变量的赋值方式为:name='value',其中"="两边一定不能有空格,如果变量值中包含有空格则需要使用引号引起来,需要注意的是强引用和弱引用的区分.此外变量的赋值也可以引用变量和命令,如果引用变量赋值需要使用双引号,如果引用命令赋值需要使用反向单引号.变量的引用需要使用"$"符号,如引用变量PATH:$PATH 或 ${PAT

经典实用的自动创建Bash脚本文件头的脚本

今天给大家展示一下,我自己写的一个自动创建Bash脚本文件头的脚本(名为create),希望能对初学脚本者带来一定的思维提示.毕竟对于一个经常写脚本的运维人员来说,每次写脚本的时候都需要重复的去写一遍文件头,也是一件很累赘的事情,既然我们学了脚本,为什么不让它来为我们减轻一下负担了.所以一个自动创建Bash脚本文件头的想法在我脑海里面产生了. 本脚本所需要实现的功能: 1,能够自动创建一个标准的Bash脚本文件头,带有详细注释信息 2,能够给新建完成的Bash脚本文件自动添加执行权限 [[ema