码迷,mamicode.com
首页 > 系统相关 > 详细

Shell编程基础

时间:2018-09-02 17:13:25      阅读:175      评论:0      收藏:0      [点我收藏+]

标签:环境   osi   表达   $@   ado   null   方式   弱类型   umask   

Shell编程

一.程序简介

程序

程序:算法+数据结构
数据结构:数据在计算机中的类型和组织方式
算法:处理数据的方式

面向过程:以指令为中心,数据服务于指令
面向对象:以数据为中心,指令服务于数据

计算机:二进制执行

高级编程语言:

编译:高级语言->编译器->机器代码->执行
解释:高级语言->执行->解释器->机器代码 shell

三大逻辑

顺序、循环、选择

二.shell脚本

1.格式

格式要求:首行shebang机制
#!/bin/bash  指定shell类型
# 注释
程序名,作用说明,版本信息,作者信息

bash -n 检查语法错误
bash -x 跟踪调试脚本的执行过程

2.变量

变量的类型:

字符、整型
强类型
弱类型
不需要声明变量类型
不支持浮点型
都以字符串的形式存储

命名规则:

不能是内部命令、系统关键字
字母、数字、下划线
不能以数字开头

定义变量

a=linux
a=‘linux‘
a="linux"
上面三个都是把linux这个字符串赋值给变量a,如果赋值的一方当中没有空格,则不用引号,如果有空格则必须用引号。

使用变量

echo $a
echo ${a}
调用变量a,在变量前面加上$即可,变量用{}括起来是个良好的习惯

已经定义的变量也可以重新赋值
a=centos
unset a 删除变量
readonly a 只读变量,不能修改

单双引号的区别

单引号 ‘‘ 强引用,单引号里所有内容都作为字符输出
双引号 "" 若引用,双引号里有变量的时候,会读取变量值输出,而不是直接输出

把命令执行结果赋值给变量

a=`cat /etc/fstab` 使用反向单引号
a=$(cat /etc/fstab) 使用$()
反向单引号容易和单引号混淆,因此推荐使用$()

局部变量和全局变量

局部变量:生效范围是当前shell进程 
全局变量:生效范围是当前shell及其子进程
export a 声明全局变量
set 显示变量,自定义和系统自带的
export 或 declare 显示环境变量

echo $PPID 显示父进程编号
pstree -p 显示进程信息
source 运行的脚本在本bash环境下,会修改某些当前bash下的环境。
bash  运行脚本时会新开一个bash,为当前bash的子进程,不会影响当前环境

SHLVL 变量,shell 的嵌套深度
echo $_ 上一个命令的最后一个字符串
unset name 删除变量,除了只读变量
readonly 查看只读变量  declare -r 

(umask=0022;touch a) 
() 不开启子进程
{} 开启子进程

位置变量

$$ 当前shell的ID
$1 第一个参数
$* 所有参数,认为所有参数是一个整体
$@ 所有参数,认为所有参数是独立的个体
$# 参数数量
$0 当前脚本的文件名
10以上的加{}
shift n 变量按顺序往前移动n个变量
set -- 清除变量

退出状态

$? 变量保存最近(前一个)的命令退出状态
0 代表成功,1-255 代表失败
脚本里指定返回值 exit 10 

2.运算

bash支持算术运算、关系运算、布尔运算、字符串运算和文件测试运算等

算术运算

expr 2 + 4
echo `expr 2 + 4
a=`expr 2 + 4`
c=`expr $a + $b`
expr是一款表达式计算工具,数值和运算符之间必须有空格,调用整个表达式的时候记得加``

let sum=x+y
$[x+y]
$((x+y))
expr 2 + 3 expr是一个命令
declare -i n=10  指定n是个整数,声明变量
-= += -- ++ 
运算符 说明 举例
+ 加法 `expr $a + $b
- 减法 `expr $a - $b
* 乘法 `expr $a \* $b
/ 除法 `expr $a / $b
% 取余 `expr $a % $b
= 赋值 a=$b
== 比较两个数字是否相等 [ $a == $b ]
!= 比较两个数是否不等 [ $a != $b ]

表达式和[ ]之间需要有空格

逻辑运算

true 1 ;false 0;
与 & 有0即0
或 | 有1即1
非 ! 取反
短路与 && 前一个为假则不再判断第二个
短路或 || 前一个为真则不再判断第二个
异或 ^ 相同为假,相异为真
同或 相同为真,相异为假

测试命令:

test 不支持正则表达式,没值就为假,变量加“” 
[[]] 支持正则表达式
[]  有值就为真
[] 和变量之间要加空格

几种括号的用法

(; ; ) 几个命令一起执行,开启子shell
{; ; } 几个命令一起执行,不开启子shell,前后空格,最后一个加;号
[] 逻辑判断,不支持正则表达式
[[]] 逻辑判断,支持正则表达式,一般用[]
=~  匹配,字符串不要加"",支持正则表达式 
!= 不等
== 相等,字符串不要加"",支持通配符

关系符运算

数值测试,不支持字符
运算符 说明 全称
-gt 是否大于 greater than
-ge 是否大于等于 greater than equal
-eq 是否等于 equal
-ne 是否不等于 no equal
-lt 是否小于 less than
-le 是否小于等于 less equal

字符串测试

= 是否等于
> ascii码是否大于
< 是否小于
!= 是否不等于
=~ 左侧字符串是否能够被右侧的pattern匹配,一般用于[[]]中
-z "string" 字符串是否为空,空为真,非空为假
-n "string" 字符串是否不空,不空为真,空位假

文件测试

-a / -e file :文件存在性测试,存在未真,否则为假
-b 是否存在且为块设备文件
-c 是否存在且为字符设备文件
-d 是否存在且为目录文件
-f 是否存在且为普通文件
-h / -L :存在且为链接文件
-p 是否存在且为命名管道文件
-S 是否存在且为套接字文件

权限测试

-r 是否存在且可读
-w 是否存在且可写
-x 是否存在且可执行
-u 是否存在且拥有suid权限
-g 是否存在且拥有sgid权限
-k 是否存在且拥有sticky权限

文件属性

-s 是否存在且为非空
-t 文件描述符是否在某终端打开
-N 文件自从上一次被读取之后是否被修改
-O 当前有效用户是否为文件时属主
-G 当前用户是否为文件属组

双目测试

file1 -ef file2:1是否是2的硬链接
file1 -nt file2:1是否新于file2
file1 -ot file2:1是否旧于file2
-a 并且
-o 或者
! 非

3.字符串

单引号

str=‘this is a string‘ 
单引号里的任何字符都会原样输出,单引号里的变量是无效的
单引号字符串中不能出现单引号,对单引号转义后也不行

双引号

str="you name is $name"
双引号里可以有变量
双引号里可以出现转义字符

拼接字符串

firstname="zhang"
lastname="hw"
echo $firstname $lastname   输出:zhanghw

获取字符串长度

str="abcd"
echo ${#str}     输出:4 

提取子字符串

str="daxiong is the best girl"
echo ${str:1:4}  1:4 起始字符到终止字符,由0开始

查找子字符串

str="daxiong is the best girl"
echo `expr index "$str" is`

4.数组

只支持一维数组,没有限定数组大小。数组元素下表从0开始,下表可以是整数或算术表达式,其值应大于或等于0

定义

用括号来定义数组,各个元素间用空格分开,如下:
array_name=(value0 value1 value2)

单独定义
array_name[0]=value0
array_name[1]=value1

引用

${array_name[index]}
a=${array_name[0]}

${array_name[@}}  
${array_name[*]} @或* 可以获取数组中的所有元素

获取数组的长度

a=${#array_name[@]} 取得数组元素的个数 @或*都可以
a=${#array_name[n]} 取得下标为n的元素的长度

5.shell printf

printf命令用于格式化输出,printf由POSIX标准所定义,移植性比echo好

printf "hello\n" 输出字符串,printf不自带换行,需要在字符串最后添加\n
printf format-string [arguments]
format-string为双引号

$ printf "%d %s\n" 1 "abc"
1 ab

格式只指定了一个参数,但多出的参数仍然会按照该格式输出,format-string 被重用
$ printf %s abc def
abcdef

$ printf "%s\n" abc def
abc
def

$ printf "%s %s %s\n" a b c d e f g h i j
a b c
d e f
g h i
j

如果没有 arguments,那么 %s 用NULL代替,%d 用 0 代替
$ printf "%s and %d \n" 
and 0

6.if else 语句

  • if...fi
  • if...else...fi
  • if...elif...else...fi
    最后必须以fi结尾来闭合

if 语句的用法

if [ expression ]
then
    Statement(s) to be executed if expression is true
fi
如果expression返回ture,then后面的语句将会被执行;如果返回false则跳出循环

if..else...fi 语句的用法

if [ expression ]
then
    Statement(s) to be executed if expression is true
else
    Statement(s) to be executed if expression is not true
fi
如果expression返回true则执行then后面的语句,否则执行else后面的语句

if...elif...fi 语句的用法

if [ expression 1 ]
then 
    Statement(s) to be executed if expression 1 is true
elif [ expression 2 ]
then
    Statement(s) to be executed if expression 2 is true
else
    Statement(s) to be executed if no expression is true
fi
哪一个expression 的值为true,就执行那个expression后面的语句,如果都为false则执行else后面的语句

7.for循环

for varibale in 列表
do
    command1
    command2
    ...
    conmmandN
done
列表是一组数值(数值、字符串等)组成的序列,每个值通过空格分格。每循环一次,就将列表中的下一个值赋给变量
in 列表是可选的,如果不用它,for循环使用命令行的位置参数

seq 列表的产生
wait 

8.while循环

  • while循环用于不断执行一系列命令,也用于从输入文件中读取数据;命令通常为测试条件

    while command
    do
    Statement(s) to be executed if command is true
    done

: 代表true的意思

9.until循环

  • 直到型循环,当执行结果为true时才跳出循环。

    until command
    do
    Statement(s) to be executed until command is true
    done

10.continue

跳过本次循环
> break [N] 直接结束第N层的本轮循环,而直接进入下一轮判断,最内层为第1层,默认值为1
    while command1 
    do
        if command2 
        then
            continue
        fi
    done

11.break

跳出整个循环
break [N] 提前结束第N层循环,最内层为第一层
while command1
do
    if command2 
    then
        break
    fi
done

12.shift

shift [n]
将参量列表list左移指定次数,缺省为左移一次。列表list一旦被移动,最左端的那个参数就从列表中删除。

#!/bin/bash
#step through all the positional parameters
until [ -z "$1" ] 
do
    echo "$1"
    shift
done
echo

13.select

select variable in list 
    do 
        循环体命令
    done

select 循环主要用于创建菜单,按数字顺序排列的菜单项将显示在
标准错误上,并显示 PS3 提示符,等待用户输入
用户输入菜单列表中的某个数字,执行相应的命令
用户输入被保存在内置变量 REPLY 中

select 是个无限循环,因此要记住用 break 命令退出循环,或用
exit 命令终止脚本。也可以按 ctrl+c 退出循环
select 经常和 case 联合使用
与 for 循环类似,可以省略 in list,此时使用位置参量

14.while特殊用法

while read line
do
    循环体
done < /path/from/somefile

依次读取/path/from/somelife 文件中的每一行,且将行赋值给变量line

15.case...esac

  • case...esca 是一种多分支选择结构
  • case语句匹配一个值或一个模式,如果匹配成功,执行相匹配的命令。

    case VALUE in
    mode1)
    command 1
    command 2
    command 3
    ;;
    mode2)
    command1
    command2
    command3
    ;;
    esac
    取值后面必须为关键字in,每一模式必须以右括号结束。取值可以为变量或常数。
    ;; 与其他语言中的break 类似,意思是跳到整个case语句的最后。

Shell编程基础

标签:环境   osi   表达   $@   ado   null   方式   弱类型   umask   

原文地址:http://blog.51cto.com/8031757/2169106

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!