小知识:
在bash环境中变量有各自的范围,有些的变量无法超出自己本身的范围,也无法更改自己,
或提升自己的能力范围
用source命令执行脚本,会对里面的变量发生改变包括范围
例:命令行中写name=wang 脚本中写name=xdg 先命令行,再脚本,最后命令行的顺序依次执行
1.正常的执行脚本 ./file.sh
输出的结果: wang xdg wang
2.用source执行脚本 source ./file.sh
输出的结果: wang xdg xdg
常量的有效时间是等于进程的时间
例:name=xdg; (name=mage; echo $name; name=wang; echo $name); echo $name
结果:mage wang xdg
注:在括号或者是括号外的 ; 分号一定要注意!()表示的是开启一个子进程,
并不在当前的bash中,如果在()里写入exit命令,只会退出当前的(),而不会退出当前的脚本。
例:name=xdg; { name=mage; echo $name; name=wang; echo $name; }; echo $name
结果:mage wang wang
在{}里代表是一个匿名函数的形式,同样注意;的位置,还有{}边上的空格要有
里面修改了变量的值,同样在外面也有效
编程语言:
低级:汇编
高级:
编译:高级语言–>编译器–>目标代码
java,C#
解释:高级语言–>解释器–>机器代码
shell, perl, python
格式要求:首行shebang机制
#!/bin/bash
#!/usr/bin/python
#!/usr/bin/perl
注:因为当前系统默认的为bash,所以可有可无,如果换了其它系统或环境
会导致运行出错,当前系统用的语言不一定是bash,所有还是把当前的环境给写出来。
shell脚本的用途有:
自动化常用命令
执行系统管理和故障排除
创建简单的应用程序
处理文本或文件
运行脚本
给予执行权限,在命令行上指定脚本的绝对或相对路径
直接运行解释器,将脚本作为解释器程序的参数运行
脚本测试
检测脚本中的语法错误
bash -n /path/to/some_script
调试执行
bash -x /path/to/some_script
强类型:变量不经过强制转换,它永远是这个数据类型,不允许隐式的类型转换。
一般定义变量时必须指定类型、参与运算必须符合类型要求;
调用未声明变量会产生错误 如 java,c#
弱类型:语言的运行时会隐式做数据类型转换。无须指定类型,默认均为字符型;
参与运算会自动进行隐式类型转换;变量无须事先定义可直接调用
如:bash 不支持浮点数,php
根据变量的生效范围等标准:
本地变量:生效范围为当前shell进程;对当前shell之外的其它shell进程,
包括当前shell的子shell进程均无效
变量赋值:name=‘value’
可以使用引用value:
(1) 可以是直接字串:name=”root”
(2) 变量引用:name=”$USER”
(3) 命令引用:name=COMMAND
或 name=$(COMMAND)
变量引用:${name} $name
注:有些时候要括起来,例:显示第10个数,不能写成$10,会识别成$1+0
“”:弱引用,其中的变量引用会被替换为变量值
”:强引用,其中的变量引用不会被替换为变量值,而保持原字符串
显示已定义的所有变量 :set
删除变量: unset name
环境变量:生效范围为当前shell进程及其子进程
变量声明、赋值:
export name=VALUE
declare -x name=VALUE
变量引用:$name, ${name}
显示所有环境变量:
env
printenv
export
declare -x
删除变量: unset name
bash中内建的环境变量
PATH 命令执行查找路径
SHELL 当前系统的shell
USER 当前系统的UID(名字)
UID 当前系统的UID (数字)
HOME 当前系统的家目录
PWD 当前系统路径
SHLVL 当前进程的深度(查看 pstree )
LANG 当前系统的语言和编码 LANG=en_US.UTF-8
MAIL 当前用户的邮件家目录 MAIL=/var/spool/mail/root
HOSTNAME 当前系统的主机名
HISTSIZE 命令历史的最大长度
_ 上个命令的最后一个字符串 (下划线)
注:如果有参数就是最后一个参数,如果没有则就是命令(最后一个字符串)
局部变量:生效范围为当前shell进程中某代码片断(通常指函数)
位置变量:$1, $2, …来表示,用于让脚本在脚本代码 中调用通过命令行传递给它的参数
位置变量:在脚本代码中调用通过命令行传递给脚本的参数
$1, $2, …:对应第1、第2等参数,
shift [n]换位置 注:就是把当前指向第一个数的指针,向后移动n位(这个是累加)
例:shift 2;shift 2; 这是移动了4位
$0: 命令本身 单单只是命令的本身,不带有任何的参数
$*: 传递给脚本的所有参数,全部参数合为一个字符串
$@: 传递给脚本的所有参数,每个参数为独立字符串
$#: 传递给脚本的参数的个数
注: $@ $* 只在被双引号包起来的时候才会有差异,没有””是没有区别的
注: set — 清空所有位置变量参数
特殊变量:
$? 上个命令的执行的结果(正确执行 0 非正确执行 非0)
$$ 当前进程的PID 如:当前进程的父进程的PID: $PPID
$- 例:echo $- –> himBH
h:hashall,打开这个选项后,Shell 会将命令所在的路径 hash下来,避免每次都要查询。
通过set +h将h选项关闭
i:interactive-comments,包含这个选项说明当前的 shell 是一个交互式的 shell。
所谓的交互式shell,在脚本中,i选项 是关闭的。
m:monitor,打开监控模式,就可以通过Job control来控制 进程的停止、继续,后台或者前台执行等。
B:braceexpand,大括号扩展
H:history,H选项打开,可以展开历史列表中的命令,可以 通过!感叹号来完成
例如“!!”返回上最近的一个历史命令, “!n”返回第 n 个历史命令
只读变量:
声明只读变量:
readonly name
declare -r name
查看只读变量:
readonly –p
bash自定义退出状态码
exit [n]:自定义退出状态码
注意:脚本中一旦遇到exit命令,脚本会立即终止;终止退出状态取决于exit命令后面的数字
注意:如果未给脚本指定退出状态码,整个脚本的退出状态码取决于脚本中执行的最后一条命令的状态码
bash中的算术运算:help let
+, -, *, /, %取模(取余), **(乘方)
实现算术运算: 如: a=5 b=7 c
(1) let var=算术表达式
let c=a+b
(2) var=$[算术表达式]
c=$[a+b] 比如:echo $[a+b]
(3) var=$((算术表达式))
c=$((a+b)) 比如:echo $((a+b))
(4) var=$(expr arg1 arg2 arg3 …)
c=$(expr 2+3)
c=$(expr $a+$b)
注:如果单单的expr的写法,在下面
(5) declare –i var = 数值
declare -i c=a+b
(6) echo ‘算术表达式’ | bc
echo $[a+b] | bc
echo 3+5 | bc
注:无法识别当中的变量
乘法符号有些场景中需要转义,如*
注:1 expr 0 + 0 ——> echo $? ——> 1
注:0 + 0 之间必须要有空格表示出来,不然出错,再运算结果为0的话,运行的状态是有问题的(非0)
2 let i=0 echo $i 输出结果为:0 —> 但是程序的运行的状态 —> 是非0的
例:k=0;let k++;echo $? —>输出的结果也是非0
k=0;let ++k;echo $? —>输出的结果也是0
bash有内建的随机数生成器:
$RANDOM(0-32767)
echo $[$RANDOM%50] :0-49之间随机数
增强型赋值:
+=, -=, *=, /=, %=
let varOPERvalue
例如:let count+=3
自加3后自赋值
自增,自减:
let var+=1
let var++
let var-=1
let var-
短路运算
短路与
第一个为0,结果必定为0
第一个为1,第二个必须要参与运算
短路或
第一个为1,结果必定为1
第一个为0,第二个必须要参与运算
异或:^ 异或的两个值,相同为假,不同为真
例:如何把两个整数变量的值给调换,而且不用第三者。
a=10; b=6; a=$[a^b]; b=$[a^b]; a=$[a^b];
a 110011011 c 111001101
b 001010110 —> b 001010110 注:两者的运算的结果
异或c 111001101 异或结果a 110011011
测试命令: 注意:EXPRESSION前后必须有空白字符,格式要求。
test EXPRESSION 不支持
注:有些变量的时候,须要引号引起来才能判断出来
[root@centos7 ~]# aa=””
[root@centos7 ~]# echo $aa
[root@centos7 ~]# test $aa && echo true 为假
[root@centos7 ~]# test “$aa” && echo true 为假
[root@centos7 ~]# aa=” ”
[root@centos7 ~]# echo $aa
[root@centos7 ~]# test $aa && echo true 为假
[root@centos7 ~]# test “$aa” && echo true 为真
true
[ EXPRESSION ] 不支持,里面的 <,>都需要转意
[root@centos7 ~]# unset a
[root@centos7 ~]# [ $a == “wang” ]
-bash: [: ==: unary operator expected 出错信息
[root@centos7 ~]# [ “$a” == “wang” ] 必须引号引起来
[root@centos7 ~]#
例:有的地方会出来这种写法: [ X$a == X”wang” ] 或 [ X”$a” == X”wang” ]
上面两个都可以,第一个是,添加额外的字符,来判断。
注: [ id ] && { a=10; echo $a; } || echo Hello 在测试的时候{}外是没有;号的,并且{}里面的 空格 要有
[[ EXPRESSION ]] 支持正则表达式
根据退出状态而定,命令可以有条件地运行
&& 代表条件性的AND THEN
|| 代表条件性的OR ELSE
-v VAR
变量VAR是否设置
数值测试:
-gt 是否大于
-ge 是否大于等于
-eq 是否等于
-ne 是否不等于
-lt 是否小于
-le 是否小于等于
字符串测试:
== 是否等于
> ascii码是否大于ascii码
< 是否小于
!= 是否不等于
=~ 左侧字符串是否能够被右侧的PATTERN所匹配
注意: 此表达式一般用于[[ ]]中;扩展的正则表达式
[root@centos6 xdg]# [[ $sh =~ “.*.sh$” ]]
[root@centos6 xdg]# echo $?
1
注:在使用的时候必须要用[[]] 用到了正则表达式,中间的空格也不能少
例:[root@centos6 ~]# str=abc;[[ $str == “abc” ]] && echo tree
tree
[root@centos6 ~]# str=abc;[[ $str =~ “abc” ]] && echo tree
tree
[root@centos6 ~]# str=abc;[[ $str =~ “^a” ]] && echo tree
[root@centos6 ~]# str=abc;[[ $str =~ ^a ]] && echo tree
tree
-z “STRING“ 字符串是否为空,空为真,不空为假
[root@centos7 ~]# aa=xxx
[root@centos7 ~]# [ -z “$aa” ] && echo true 为假
[root@centos7 ~]# [ -z ‘$aa’ ] && echo true 为假
[root@centos7 ~]# aa=””
[root@centos7 ~]# [ -z ‘$aa’ ] && echo true 为假
[root@centos7 ~]# [ -z “$aa” ] && echo true 为真
true
-n “STRING“ 字符串是否不空,不空为真,空为假
注意:用于字符串比较时的用到的操作数都应该使用引号,如上test一样
存在性测试
-a FILE:同-e
-e FILE: 文件存在性测试,存在为真,否则为假
存在性及类别测试
-b FILE:是否存在且为块设备文件
-c FILE:是否存在且为字符设备文件
-d FILE:是否存在且为目录文件
-f FILE:是否存在且为普通文件
-h FILE 或 -L FILE:存在且为符号链接文件
注:在判断一个文件是否存在时,要先判断它是否是一个符号链接文件
-p FILE:是否存在且为命名管道文件
-S FILE:是否存在且为套接字文件
文件权限测试: 测试文件,首先判断是否是软硬链接
-r FILE:是否存在且可读
-w FILE: 是否存在且可写
-x FILE: 是否存在且可执行
文件特殊权限测试:
-u FILE:是否存在且拥有suid权限
-g FILE:是否存在且拥有sgid权限
-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(mtime)
FILE1 -ot FILE2: FILE1是否旧于FILE2
第一种方式:
COMMAND1 && COMMAND2 并且
COMMAND1 || COMMAND2 或者
! COMMAND 非
如:[[ -r FILE ]] && [[ -w FILE ]]
第二种方式:
EXPRESSION1 -a EXPRESSION2 并且
EXPRESSION1 -o EXPRESSION2 或者
! EXPRESSION 必须使用测试命令进行
使用read来把输入值分配给一个或多个shell变量
-p 指定要显示的提示
-s 静默输入,一般用于密码
-n N 指定输入的字符长度N
-d ‘字符’ 输入结束符
-t N TIMEOUT为N秒
read 从标准输入中读取值,给每个单词分配一个变量 所有剩余单词都被分配给最后一个变量
read -p “Enter a filename: “ FILE
注:在shell脚本中,运行的优先级
把命令行分成单个命令词
展开别名
展开大括号的声明({})
展开波浪符声明(~)
命令替换$() 和 “)
再次把命令行分成命令词
展开文件通配(*、?、[abc]等等)
准备I/0重导向(<、>)
运行命令
反斜线(\)会使随后的字符按原意解释
$ echo Your cost: \$5.00
Your cost: $5.00
加引号来防止扩展
单引号(’)防止所有扩展
双引号(”)也防止所有扩展,但是以下情况例外:
$(美元符号) - 变量扩展
`(反引号) - 命令替换
\(反斜线) - 禁止单个字符扩展
!(叹号) - 历史命令替换
bash的配置文件
按生效范围划分,存在两类:
全局配置: /etc/profile
/etc/profile.d/*.sh
/etc/bashrc
个人配置: ~/.bash_profile
~/.bashrc
shell登录两种方式
交互式登录:
(1)直接通过终端输入账号密码登录
(2)使用“su – UserName” 切换的用户
执行顺序:/etc/profile
–> /etc/profile.d/.sh
–> ~/.bash_profile
–> ~/.bashrc
–> /etc/bashrc
非交互式登录:
(1)su UserName
(2)图形界面下打开的终端
(3)执行脚本
(4)任何其它的bash实例
执行顺序:~/.bashrc
–> /etc/bashrc
–> /etc/profile.d/.sh
profile类
按功能划分,存在两类:
profile类和bashrc类
profile类:为交互式登录的shell提供配置
全局:/etc/profile, /etc/profile.d/*.sh
个人:~/.bash_profile
功用: (1) 用于定义环境变量
(2) 运行命令或脚本
bashrc类
bashrc类:为非交互式和交互式登录的shell提供配置
全局:/etc/bashrc
个人:~/.bashrc
功用: (1) 定义命令别名和函数
(2) 定义本地变量
编辑配置文件生效
修改profile和bashrc文件后需生效
两种方法: 1重新启动shell进程
2 . 或source
例: . ~/.bashrc
bash退出任务
保存在~/.bash_logout文件中(用户)在退出登录shell时运行用于
创建自动备份
清除临时文件
原创文章,作者:_xddggg,如若转载,请注明出处:http://www.178linux.com/83951