Linux——bash的编程环境

bash的编程环境

shell脚本:文本文件

文件的开头要写上解释程序的路径:

#!/bin/bash

#!/usr/bin/python

#!/usr/bin/perl

运行脚本:

1、给予执行权限,通过具体的文件路径(./xxx)指定文件执行;

2、直接运行解释器,将脚本作为解释器程序的参数运行;(bash xxx.sh)

bash是弱类型语言:把所有要存储的数据统统当作字符进行,而且不支持浮点数;其他的与其他语言一样

逻辑运算:

  • true, false
  • 1, 0

与:

  • 1 && 1 = 1
  • 1 && 0 = 0
  • 0 && 1 = 0
  • 0 && 0 = 0

或:

  • 1 || 1 = 1
  • 1 || 0 = 1
  • 0 || 1 = 1
  • 0 || 0 = 0

非:

  • ! 1 = 0
  • ! 0 = 1

短路运算:

与:

  • 第一个为0,结果必定为0;
  • 第一个为1,第二个必须要参与运算;

或:

  • 第一个为1,结果必定为1;
  • 第一个为0,第二个必须要参与运算;

变量的种类:

根据变量的生效范围等标准分为:

1、本地变量:

生效范围为当前shell进程;对当前shell之外的其它shell进程,包括当前shell的子shell进程均无效;

变量赋值:

  • (1) 可以是直接字串; name="username"
  • (2) 变量引用:name="$username"
  • (3) 命令引用:name=`COMMAND`, name=$(COMMAND)

变量引用:${name}, $name

  • "":弱引用,其中的变量引用会被替换为变量值;
  • '':强引用,其中的变量引用不会被替换为变量值,而保持原字符串;

显示已定义的所有变量:set

销毁变量:unset 变量名

2、环境变量:

生效范围为当前shell进程及其子进程;

变量声明、赋值:

  • export name=VALUE
  • declare -x name=VALUE

变量引用:$name, ${name}

显示所有环境变量:export,env,printenv

销毁:unset name

bash有许多内建的环境变量:PATH, SHELL, UID, HISTSIZE, HOME, PWD, OLD, HISTFILE, PS1

3、只读变量(常量):

定义只读变量后,不可修改,不可销毁,直到当前shell进程结束后,自动销毁;

readonly name[=value]  # 当定义了一个本地变量,可以直接使用readonly 变量名/declare -r 变量名,将其改为只读变量;

declare -r name[=value]  # 也可以直接通过readonly 变量名=值/declare -r 变量名=值,直接定义只读变量

4、位置变量:

$1, $2, ...来表示,用于让脚本在脚本代码中调用通过命令行传递给它的参数;

$1, $2, ...:对应调用第1、第2等参数;

shift [n]:踢掉n个传来的变量;

$0: 命令本身;

$*: 传递给脚本的所有参数;

$@: 传递给脚本的所有参数;

$#: 传递给脚本的参数的个数;

5、局部变量:

生效范围为当前shell进程中某代码片断(通常指函数);

算数运算

实现算术运算:+, -, *, /, %, **

(1) let var=算术表达式

(2) var=$[算术表达式]

(3) var=$((算术表达式))

(4) var=$(expr arg1 arg2 arg3 ...)  # 被操作数 符号 第二个操作数...

  • 乘法符号有些场景中需要转义;
  • bash有内建的随机数生成器:$RANDOM

增强型赋值

自增:let var+=1,let var++

自减:let var-=1,let var--

 1 练习1:写一个脚本
 2     计算/etc/passwd文件中的第10个用户和第20用户的ID之和;
 3 
 4         #!/bin/bash
 5         userid1=$(head -n 10 /etc/passwd | tail -n 1 | cut -d: -f3)
 6         userid2=$(head -n 20 /etc/passwd | tail -n 1 | cut -d: -f3)
 7 
 8         useridsum=$[$userid1+$userid2]
 9 
10         echo "uid sum: $useridsum"
11 
12 练习2:写一个脚本
13     传递两个文件路径作为参数给脚本,计算这两个文件中所有空白行之和;
14 
15         #!/bin/bash
16 
17         spaceline1=$(grep "^[[:space:]]*$" $1 |    wc -l)
18         spaceline2=$(grep "^[[:space:]]*$" $2 |    wc -l)
19 
20         echo "The sum of space line: $[$spaceline1+$spaceline2]"
21 
22 练习3:统计/etc, /var, /usr目录共有多少个一级子目录和文件;
View Code

条件测试:

判断某需求是否满足,需要由测试机制来实现;

Note: 专用的测试表达式需要由测试命令辅助完成测试过程;

测试命令:

(1)test EXPRESSION

(2)[ EXPRESSION ]

(3)[[ EXPRESSION ]]

  • 小Tips: EXPRESSION前后必须有空白字符;

bash的测试类型

数值测试:符合结果是0,不符合是1(因为命令执行成功了返回0,失败返回1)

  • -gt: 是否大于;
  • -ge: 是否大于等于;
  • -eq: 是否等于;
  • -ne: 是否不等于;
  • -lt: 是否小于;
  • -le: 是否小于等于;

字符串测试:符合结果是0,不符合是1

  • ==:是否等于;
  • >: 是否大于;
  • <: 是否小于;
  • !=: 是否不等于;
  • =~: 左侧字符串是否能够被右侧的PATTERN所匹配;
    • Note: 此表达式一般用于[[ ]]中;
  • -z "STRING":测试字符串是否为空,空则为真,不空则为假;
  • -n "STRING":测试字符串是否不空,不空则为真,空则为假;
    • Note:用于字符串比较时的用到的操作数都应该使用引号;

文件测试:

存在性测试:

  • -a FILE
  • -e FILE: 文件存在性测试,存在为真,否则为假;

存在性及类别测试

  • -b FILE:是否存在且为块设备文件;
  • -c FILE:是否存在且为字符设备文件;
  • -d FILE:是否存在且为目录文件;
  • -f FILE:是否存在且为普通文件;
  • -h FILE 或 -L FILE:存在且为符号链接文件;
  • -p FILE:是否存在且为命名管道文件;
  • -S FILE:是否存在且为套接字文件;

文件权限测试:

  • -r FILE:是否存在且可读
  • -w FILE: 是否存在且可写
  • -x FILE: 是否存在且可执行

文件特殊权限测试:

  • -g FILE:是否存在且拥有sgid权限;
  • -u FILE:是否存在且拥有suid权限;
  • -k FILE:是否存在且拥有sticky权限;

文件大小测试:

  • -s FILE: 是否存且非空;

文件是否打开:

  • -t fd: fd表示文件描述符是否已经打开且与某终端相关

-N FILE:文件自动上一次被读取之后是否被修改过;

-O FILE:当前有效用户是否为文件属主;

-G FILE:当前有效用户是否为文件属组;

双目测试:

  • FILE1 -ef FILE2: FILE1与FILE2是否指向同一个设备上的相同inode(节点)
  • FILE1 -nt FILE2: FILE1是否新于FILE2;
  • FILE1 -ot FILE2: FILE1是否旧于FILE2;

组合测试条件:

逻辑运算:

第一种方式:

  • COMMAND1 && COMMAND2
  • COMMAND1 || COMMAND2
  • ! COMMAND
  • [ -e FILE ] && [ -r FILE ]

第二种方式:

  • EXPRESSION1 -a EXPRESSION2
  • EXPRESSION1 -o EXPRESSION2
  • ! EXPRESSION

必须使用测试命令进行;

示例:

# [ -z "$hostName" -o "$hostName"=="localhost.localdomain" ] && hostname www.magedu.com

# [ -f /bin/cat -a -x /bin/cat ] && cat /etc/fstab

bash自定义退出状态码

exit [n]:自定义退出状态码;

注意:脚本中一旦遇到exit命令,脚本会立即终止;终止退出状态取决于exit命令后面的数字;

注意:如果未给脚本指定退出状态码,整个脚本的退出状态码取决于脚本中执行的最后一条命令的状态码;

1 练习:写一个脚本
2     接受一个文件路径作为参数;
3         如果参数个数小于1,则提示用户“至少应该给一个参数”,并立即退出;
4         如果参数个数不小于1,则显示第一个参数所指向的文件中的空白行数;
View Code

if条件语句

格式:

if 判断条件
then
	条件为真的分支代码
fi

或

if 判断条件; then
	条件为真的分支代码
else
	条件为假的分支代码
fi

示例代码:

#!/bin/bash
# -*- coding:utf-8 -*-

if [ $# -lt 1 ];then    # 如果输入的字符串小于1,则执行
    echo "请输入用户名!"
    exit 1  # 自定义退出状态码
fi  # 结束if

if id $1 &> /dev/null;then  # 如果当前用户存在,则执行,将结果扔掉
    echo "用户 $1 已存在"
    exit 0

else
    useradd $1  # 添加用户
    [ $? -eq 0 ] && echo "$1" | passwd --stdin $1 &> /dev/null
    # 判断添加用户是否成功($?=0),成功的话为用户添加密码为‘用户名’

fi

运行结果:

[root@localhost xin]# bash test.sh 
请输入用户名!
[root@localhost xin]# echo $?
1
[root@localhost xin]# bash test.sh x5456
用户 x5456 已存在
[root@localhost xin]# echo $?
0
[root@localhost xin]# bash test.sh x54256
[root@localhost xin]# echo $?
0
原文地址:https://www.cnblogs.com/x54256/p/8149180.html