【shell基础】0七、bash脚本编程入门及变量



1、shellhtml

一、shell是什么java

     在计算机语言中,shell是指一种命令行解释器,是为用户和操做系统之间通讯提供的一种接口。python

它接受来自用户输入的命令,并讲其转换为一系列的系统调用送到内核执行,并将结果输出给用户。
linux


二、shell分为两大类redis

一类是图形界面shell(Graphical User Interface):shell

                  Gnome,KDE,Xface(嵌入式轻量级桌面系统)编程

另外一类是命令行式shell(command Line Interface):vim

                 sh,bash,ksh,zsh,tcshwindows

查看系统使用的shell:数组

[root@Node3 ~]# cat /etc/shells   #系统默认安装的shell
/bin/sh
/bin/bash
/sbin/nologin
/bin/dash
[root@Node3 ~]# echo $SHELL      #当前使用的shell
/bin/bash
[root@Node3 ~]# bash --version
GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

  事实上,shell不仅是一种解释器(在用户和系统间骑着桥梁的做用) ,仍是一种编程工具,称为脚本语言。脚本语言又被称做解释型语言   

   

三、shell的功能

       当一台系统运行起来时,内核会被调入内存中运行,由内核执行全部底层的工做,它会将全部应用程序及用户的操做翻译成CPU的基本指令,并将其送至处理器。这些过程听起来很是复杂,并且实际上也确实是很是底层的和技术化的。为了对用户屏蔽这些复杂的技术细节,同时也为了保护内核不会由于用户直接操做而受到损害,有必要在内核之上建立一个层,该层就是一个‘壳’,这就是shell的由来。


四、解释和编译

      计算机不能理解高级语言,只能理解机器语言,全部必须把高级语言翻译为机器码。而这种翻译的方式有2类:

编译:

      编译器:源程序(文本文件)-->预处理-->编译-->汇编-->连接

      编译型语言也被称为静态语言:是指在编译时变量的数据类型便可肯定的语言,多数静态类型语言要求在使用变量以前必须声明数据类型,如c,java

解释:

       解释器:解释器可独立运行,解释器运行代码

             词法分析

             语法分析

             语义分析

      源程序(文本文件)-->解析器读取并执行

      解释器也被称为动态语言: 是在运行时肯定数据类型的语言。变量使用以前不须要类型声明,一般变量的类型是被赋值的那个值的类型,如,python,bash,perl

编译和解释不一样之处:

        翻译的时间不一样,编译型语言是运行前翻译,通常是使用编译工具讲程序源码处理成机器认识的可执行文件(好比:windows上的exe文件,linux下的二进制执行文件),这种文件一旦产生,之后运行时,将不须要须要再次翻译,全部编译型语言效率较高;而解释型语言是运行时翻译,执行一条语句就当即翻译一条,并且每次执行程序都须要进行解释,相对来讲效率较低。


五、过程式编程语言

顺序执行

选择执行:

       测试条件,当条件知足时,执行其中对应条件下的那部分代码

循环执行:

       一段代码被反复执行屡次,循环语句须要退出条件


六、bash shell有两种工做模式

互动模式:所谓互动模式就是输入命令,等待期执行完毕后再执行吓一跳命令

脚本模式:使用bash提供控制机制,将指望执行的命令罗列于文本文件中

                 bash没有库,整个程序几乎都要依赖于命令


2、bash编程入门

一、shebang

linux可执行文件的格式是ELF

[root@Node3 tmp]# file /bin/ls    #ELF格式的文件能够执行
/bin/ls: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, stripped
[root@Node3 tmp]# file memory.txt 
memory.txt: ASCII text

#!/bin/bash            #指定解释器的路径,内核调用对应的解释器来解释脚本

脚本中常交待的信息:

#!/bin/bash  
#Description:
#Version:
#Author:
#License:
#Datetime:

脚本文件中以#开头的行均为注释行,将会被解释器忽略


二、运行脚本

      内核会启动一个专门的shell进程(是当前shell的子进程)来运行程序文件,脚本运行结束,此shell进程也即终止

运行脚本的方式:

 1)给脚本执行权限,然后指定路径来运行

          内核会经过读取脚本文件第一行来判断启动什么解释器来运行此脚本

 2)指定给释器来运行

[root@Node3 src]# vim first.sh
[root@Node3 src]# cat first.sh 
#!/bin/bash
echo "Hello world"
[root@Node3 src]# chmod +x first.sh 
[root@Node3 src]# first.sh
-bash: first.sh: command not found
[root@Node3 src]# ./first.sh 
Hello world
[root@Node3 src]# source first.sh   #此时能够没有执行权限
Hello world
[root@Node3 src]# /tmp/src/first.sh 
Hello world
[root@Node3 src]# bash first.sh    #此时能够没有执行权限
Hello world

bash命令经常使用的选项:

   -n   注意:检查语法错误,但不会检查命令错误

   -x   调试运行  显示运行过程


三、脚本的执行结果状态返回值

脚本最后一个命令的执行结果状态返回值

自定义脚本的执行结果状态返回值:

exit [N]

注意:脚本中不管哪一个位置遇到exit命令就中止运行,退出解释器

[root@Node3 src]# cat first.sh 
#!/bin/bash
echo "Hello world"
[root@Node3 src]# bash first.sh 
Hello world
[root@Node3 src]# echo $?
0
[root@Node3 src]# echo "exit 111">>first.sh
[root@Node3 src]# bash first.sh 
Hello world
[root@Node3 src]# echo $?
111

四、shell脚本不一样的执行方法的区别

  有两种方法执行shell scripts,一种是新产生一个shell,而后执行相应的shell scripts一种是在当前shell下执行,再也不启用其余shell。
  新产生一个shell而后再执行scripts的方法是在scripts文件开头加入语句:#!/bin/sh。通常的script文件(.sh)便是这种用法。这种方法先启用新的sub-shell(新的子进程),而后在其下执行命令。
  另一种方法就是上面说过的source命令,再也不产生新的shell,而在当前shell下执行一切命令。source: source命令即点(.)命令。在 bash下输入man source,找到source命令解释处,能够看到解释"Read and execute commands from filename in the current shell environment and ..."。从中能够知道,source命令是在当前进程中执行参数文件中的各个命令,而不是另起子进程(或sub-shell)。

  source 命令是 bash shell 的内置命令,从 C Shell 而来。source 命令的另外一种写法是点符号,用法和 source 相同,从Bourne Shell而来。source 命令能够强行让一个脚本去当即影响当前的环境。source 命令会强制执行脚本中的所有命令,而忽略文件的权限。source 命令一般用于从新执行刚修改的初始化文件,如 .bash_profile 和 .profile 等等。source 命令能够影响执行脚本的父shell的环境,而 export 则只能影响其子shell的环境。


在脚本中可使用source或.为把文件当成当前脚本的配置文件(引入变量...)

[root@Note3 src]# echo $a

[root@Note3 src]# cat test1.conf 
a=111
[root@Note3 src]# source test1.conf   #在当前shell中引入变量,影响当前的shell环境
[root@Note3 src]# echo $a
111
[root@Note3 src]# cat test.sh 
#source test1.conf
echo "$a"
[root@Note3 src]# bash test.sh

[root@Note3 src]# vim test.sh
[root@Note3 src]# cat test.sh
source test1.conf                #把其它的文件当作当前脚本的配置文件
echo "$a"
[root@Note3 src]# bash test.sh
111


3、变量

一、变量是什么

       顾名思义,变量就是其值能够变化的量,从变量的本质来讲变量是指向一片用于存储数据的内存空间。

变量命名:

    一、不能使用程序中的关键字(保留字)如,if,case,for

    二、只能使用数字,字母和下划线,且不能以数字开头

    三、要见名知义

变量赋值:向变量指向的存储空间保存数据    

        VAR_NAME=VALUE     #“=”号两边不能有空格

变量引用:引用其值

        ${VAR_NAME}              # {}通常可省略

撤销变量: unset VAR_NAME 

[root@Node3 ~]# echo $name

[root@Node3 ~]# name=xj
[root@Node3 ~]# echo ${name}
xj
[root@Node3 ~]# echo $name
xj
[root@Node3 ~]# echo name
name
[root@Node3 ~]# name=3          #从新赋值
[root@Node3 ~]# echo $name
3
[root@Node3 ~]# bash            #子shell无效
[root@Node3 ~]# echo $name

[root@Node3 ~]# exit
exit
[root@Node3 ~]# unset name     #撤销变量
[root@Node3 ~]# echo $name

[root@Node3 ~]# 
[root@Node3 src]# file=test0             #
[root@Node3 src]# rm file
rm: 没法删除"file": 没有那个文件或目录
[root@Node3 src]# rm $file
rm: 没法删除"test0": 没有那个文件或目录
[root@Node3 src]# file=test1
[root@Node3 src]# rm $file
rm:是否删除普通空文件 "test1"?y

二、变量类别

本地变量:只对当前shell进程有效,对其它shell进程无效,包括当前shell的子进程     

环境变量:对当前shell及其子shell有效,对其余shell无效

       定义:export VAR_NAME=VALUE

       导出:export VAR_NAME 

只读变量: readonly VAR_NAME       #其值不能重复赋值

              用户可自定义,bash有许多内置的环境变量

局部变量:对shell脚本中某代码片断有效,一般用于函数本地

        定义: local VAR_NAME=VALUE

位置参数变量:$0$1,$2,$三、、、${10}

特殊变量:$?,$!,$#,$@,$*

$0:脚本名称自身

$?:上一条命令执行的状态返回值,

      状态用数字来表示0-255,0表示成功,非0表示失败

$$:当前程序进程号

$!:运行于后台的最后一个做业的PID

$#:脚本全部参数的个数

$@:全部的位置参数,每一个参数都是一个独立的字符串

$*:全部的位置参数,被看成一个字符串        

$-:传递给脚本的标记,不知道怎么使用

$_:上一条命令的最后一个参数

查看当前shell进程中的全部变量:set

查看当前shell进程中的全部环境变量:export,printenv,env

[root@Node3 src]# cat test.sh 
#!/bin/bash

cat << EOF
\$0 is $0
\$1 is $1
\$2 is $2
\$3 is $3
\$# is $#
\$@ is $@
\$* is $*
EOF
[root@Node3 src]# bash test.sh a b c
$0 is test.sh
$1 is a
$2 is b
$3 is c
$# is 3
$@ is a b c
$* is a b c
[root@Node3 src]# echo $?
0

三、bash数据(变量)类型

数据类型的做用?

数据存储格式不一样(文本,数值)

      例如:有var1=18,若是18是数字和是字符串,它们须要的存储空间不一样

 数字的存储     18:00010010                      只需8位
 字符串的存储   18:1:00000001 8:00001000         需16位

数据的有效存储范围不一样

比较机制不一样

参与的运算类型不一样

bash数据类型分为2类:

数值型:

      精确数值:整数

      近似数值:浮点型            #小数没法精确转换为二进制数字

               单精度浮点

               双精度浮点

字符型:(ASCII)

       char     单个字符

       string   字符串

布尔型:true(1),false(0)  #数值或字符


bash是动态弱类型语言,变量事先又不须要事先声明,那么一切变量的类型默认为字符

类型转换:显示转换(bash不支持),隐式转换    

[root@Node3 src]# a=1
[root@Node3 src]# b=2
[root@Node3 src]# echo $a
1
[root@Node3 src]# echo $a $b
1 2
[root@Node3 src]# echo $a+$b
1+2
[root@Node3 src]# echo "$a $b"
1 2
[root@Node3 src]# echo '$a $b'
$a $b


四、变量的其它用法

 ${#var}      #返回该变量字符串的长度,

[root@Node3 src]# url="magedu"
[root@Node3 src]# echo url
url
[root@Node3 src]# echo $url
magedu
[root@Node3 src]# echo ${url}
magedu
[root@Node3 src]# echo ${#url}
6

给以变量默认值:

${var:-value}

       若是var不空,其返回值var的值,不然,则返回value

var=${var:-value}  就能够实现给var默认值

[root@Node3 src]# echo $SB

[root@Node3 src]# SB=${SB:-xj}
[root@Node3 src]# echo $SB
xj
[root@Node3 src]# SB=xw
[root@Node3 src]# echo $SB
xw
[root@Node3 src]# SB=${SB:-xj}
[root@Node3 src]# echo $SB
xw

3、变量运算

bash中变量如何运算?

[root@xxj ~]# num1=4
[root@xxj ~]# num2=8
[root@xxj ~]# num=$num1+$num2
[root@xxj ~]# echo $num
4+8

为何会这样?

       由于bash中全部变量都默认是字符类型。

应该怎样进行运算呢?

一、事先申明变量的类型为数值型

运算符:+,-,*,/,%(取余,去模)

加强型赋值:+=,-=,*=,/=,%=

declare

declare  VARNAME=算数表达式     

      -i:×××变量

      -x:环境变量,相似于export


let

let VARNAME=算数表达式       


expr

expr  $num1 + $num2      #注意,符号先后要有空格,可直接获得结果,可以使用命令引用其结果


使用特殊格式$[ ],$(( ))

$[算术表达式]          

$((算术表达式))

注意:

      圆整:若是计算结果中存在小数,将会被圆整

      算术表达式中含有变量可不须要$应用,用$引用也能够(建议仍是使用)

[root@Node3 ~]# num1=1
[root@Node3 ~]# num2=2
[root@Node3 ~]# sum=$num1+$num2
[root@Node3 ~]# echo $sum          #事先声明连个加数没用
1+2
[root@Node3 ~]# declare -i sum     #事先声明值能够
[root@Node3 ~]# sum=$int1+$int2
[root@Node3 ~]# echo $sum
3
[root@Node3 ~]# a=1
[root@Node3 ~]# b=2
[root@Node3 ~]# declare -i c=$a+$b 
[root@Node3 ~]# echo $c
3
[root@Node3 ~]# a=2
[root@Node3 ~]# b=4
[root@Node3 ~]# let c=a+b
[root@Node3 ~]# echo $c
6
[root@Node3 ~]# let c=$a+b
[root@Node3 ~]# echo $c
6
[root@Node3 ~]# let c=$a+$b
[root@Node3 ~]# echo $c
6
[root@Node3 ~]# let a+b
[root@Node3 ~]#
[root@Node3 ~]# x=1
[root@Node3 ~]# y=2
[root@Node3 ~]# declare -i z=y-x
[root@Node3 ~]# echo $z
1
[root@Node3 ~]# expr x + y
expr: 参数数目错误
[root@Node3 ~]# expr $x + $y
3 
[root@Node3 ~]# expr z=$x + $y       #不能直接这样赋值,要使用命令替换
expr: 参数数目错误
[root@Node3 ~]# x=1
[root@Node3 ~]# y=2
[root@Node3 ~]# z=$[x+y]
[root@Node3 ~]# echo $z
3
[root@Node3 ~]# z=$[$x+$y]
[root@Node3 ~]# echo $z
3
[root@Node3 ~]# z=$(($x+$y))
[root@Node3 ~]# echo $z
3


4、经常使用的内置变量

  在bash中,内置变量通常是纯大写字母,函数名通常首字母大写。

经常使用的内置变量:

  PATH,PS1,HOSTNAME,UID,HISTFILE,HISTSIZE,HISTFILESIZE,HISTCONTROL


$BASH:bash二进制程序文件的文件

$BASH_VERSION:bash的版本

$BASH_SUBSHELL:子shell的层次,这个不知道咋用

$SHLVL:shll级别,bash被嵌入的深度

$SECONDS:当前脚本已经运行的时长

 

$UID:当前用户的UID号

$EUID:有效的用户ID

$GROUPS:显示当前用户GID

$HOME:当前用户的家目录

$PWD:当前路径

$OLDPWD:上一个路径

$PPID:父进程


$IFS:输入数据时字段分隔符,默认为空白符(空格,制表符,换行符)

$PS1:主提示符

$PS2:第二提示符,补充彻底输入时的提示符

$PS3:第三提示符,用于select(菜单生成器)命令中

$PS4:第四提示符,当使用-x选项调用脚本时,显示的提示符,默认为+号


$FUNCNAME:在函数中引用的,查看当前函数的名称

$EDITOR:默认编辑器


$HISTTYPE:主机类型,用来识别系统硬件(x86,x86_64)

$MACHTYPE:机器类型

$OSTYPE:OS类型

[root@Node3 ~]# echo $HOSTTYPE
x86_64
[root@Node3 ~]# echo $MACHTYPE
x86_64-redhat-linux-gnu
[root@Node3 ~]# echo $OSTYPE
linux-gnu


声明变量:

 declare

    -i:×××

    -a:数组

    -A:关联数组

    -x:环境变量   

    -r:只读变量,至关于readonly

    -f:声明函数 

相关文章
相关标签/搜索