shell常用的命令
数据检索命令
行检索:grep
字符串检索:cut tr
数据处理命令
数据排序:sort
数据去重: uniq
文本数据合并: paste
数据输出: tee
数据处理: xargs
grep用于根据关键字进行行过滤
常用选项
-i: 不区分大小写
-v: 查找不包含指定内容的行,反向选择
-w: 按单词搜索
-n: 显示行号
-A: 显示匹配行及后面多少行 -A 5
-B: 显示匹配行及前面多少行
-o: 打印匹配关键字
-c: 统计匹配到的次数
-r: 逐层遍历目录查找
-C: 显示匹配行前后多少行
-l:只列出匹配的文件名
-L:列出不匹配的文件名
-e: 使用正则匹配
-E:使用扩展正则匹配
^key:以关键字开头
key$:以关键字结尾
^$:匹配空行
--color=auto :可以将找到的关键词部分加上颜色的显示
常用
# grep -i root passwd 忽略大小写匹配包含root的行
# grep -w ftp passwd 精确匹配ftp单词
# grep -wo ftp passwd 打印匹配到的关键字ftp
# grep -n root passwd 打印匹配到root关键字的行好
# grep -ni root passwd 忽略大小写匹配统计包含关键字root的行
# grep -nic root passwd 忽略大小写匹配统计包含关键字root的行数
# grep -i ^root passwd 忽略大小写匹配以root开头的行
# grep bash$ passwd 匹配以bash结尾的行
# grep -n ^$ passwd 匹配空行并打印行号
# grep ^# passwd 匹配以#号开头的行
# grep -v ^# passwd 匹配不以#号开头的行
# grep -A 1 root passwd 匹配包含root关键字及其后1行
# grep -B 1 root passwd 匹配包含root关键字及其前1行
# grep -C 1 root passwd 匹配包含root关键字及其前后1行
cut数据截取
选项:
-c: 以字符为单位进行分割。
-d: 自定义分隔符,默认为制表符。\t
-f: 与-d一起使用,指定显示哪个区域。
常用:
[root@lc133 ceshi]# cut -d: -f1 passwd | head -2 #以:冒号分割,截取第1列内容
root
bin
[root@lc133 ceshi]# cut -d: -f1,7 passwd | head -2 #以:冒号分割,截取第1,7列内容
root:/bin/bash
bin:/sbin/nologin
[root@lc133 ceshi]# cut -c4 passwd | head -2 #截取文件中每行第4个字符
t
:
[root@lc133 ceshi]# cut -c1-4 passwd | head -2 #截取文件中每行的1-4个字符
root
bin:
[root@lc133 ceshi]# cut -c10- passwd | head -2 #从第10个字符开始截取后面所有字符
0:root:/root:/bin/bash
:bin:/bin:/sbin/nologin
tr 字符转换:替换,删除
tr用来从标准输入中通过替换或删除操作进行字符转换;主要用于删除文件中控制字符或进行字符转换。
使用tr时要转换两个字符串:字符串1用于查询,字符串2用于处理各种转换。
语法:
commands|tr 'string1' 'string2'
tr 'string1' 'string2' < filename
tr options 'string1' < filename
-d 删除字符串1中所有输入字符。
-s 删除所有重复出现字符序列,只保留第一个;即将重复出现字符串压缩为一个字符串。
a-z 任意小写
A-Z 任意大写
0-9 任意数字
例如:
[root@lc133 ceshi]# head -2 passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
[root@lc133 ceshi]# tr -d '[:/]' < passwd | head -2 #删除文件中的:和/
rootx00rootrootbinbash
binx11binbinsbinnologin
[root@lc133 ceshi]# head -2 passwd | tr -d '[:/]' #删除文件中的:和/
rootx00rootrootbinbash
binx11binbinsbinnologin
[root@lc133 ceshi]# head -2 passwd | tr '[a-z]' '[A-Z]' #将文件中的小写字母替换成大写字母
ROOT:X:0:0:ROOT:/ROOT:/BIN/BASH
BIN:X:1:1:BIN:/BIN:/SBIN/NOLOGIN
[root@lc133 ceshi]# head -2 passwd | tr '[a-z]' '*' #将文件中的小写字母替换成*
****:*:0:0:****:/****:/***/****
***:*:1:1:***:/***:/****/*******
[root@lc133 ceshi]# head -2 passwd | tr -s '[a-z]' #匹配小写字母并将重复的压缩为一个
rot:x:0:0:rot:/rot:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
[root@lc133 ceshi]# head -2 passwd | tr -s '[a-zA-Z0-9]' #匹配小写字母,大写字母和数字并将重复的压缩为一个
rot:x:0:0:rot:/rot:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
sort排序
sort:将文件的每一行作为一个单位,从首字符向后,依次按ASCII码值进行比较,最后将他们按升序输出。
语法:
sort [options] [filename]
-u :去除重复行
-r :降序排列,默认是升序
-o : 将排序结果输出到文件中 类似 重定向符号 >
-n :以数字排序,默认是按字符排序
-t :分隔符
-k :第N列
-b :忽略前导空格。
-R :随机排序,每次运行的结果均不同。
[root@lc133 ceshi]# sort -n -t: -k3 passwd | head -2 #按照用户的uid进行升序排列,默认升序
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
[root@lc133 ceshi]# sort -nr -t: -k3 passwd | head -2 #按照用户的uid进行降序排列
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
lc:x:1000:1000:lc:/home/lc:/bin/bash
[root@lc133 ceshi]# sort -n passwd | head -2 # 按照数字排序
abrt:x:173:173::/etc/abrt:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
[root@lc133 ceshi]# sort passwd | head -2 #排序
abrt:x:173:173::/etc/abrt:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
[root@lc133 ceshi]# sort passwd -o passwd.bak #按照数字排序并将结果重定向到文件
[root@lc133 ceshi]# head -2 passwd.bak
abrt:x:173:173::/etc/abrt:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
[root@lc133 ceshi]# sort -R passwd | head -2 #随机排序
ntp:x:38:38::/etc/ntp:/sbin/nologin
tss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin
[root@lc133 ceshi]# sort -R passwd | head -2 #随机排序
radvd:x:75:75:radvd user:/:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
uniq 去除连续的重复行
uniq:去除连续重复行
语法:
uniq [options] [filename]
-i: 忽略大小写
-c: 统计重复行次数
-d:只显示重复行
# uniq passwd
# uniq -d passwd
# uniq -dc passwd
tee 双向输出
tee工具从标准输入读取并写入标准输出和文件,即:双向覆盖重定向<屏幕输出|文本输入>
somecommand |tee filename
-a 双向追加重定向
[root@lc133 ceshi]# echo "hellow world" > 1.txt
[root@lc133 ceshi]# echo "nihao" | tee 1.txt # 默认覆盖文件
nihao
[root@lc133 ceshi]# cat 1.txt
nihao
[root@lc133 ceshi]# echo "hello" | tee -a 1.txt # 使用-a参数追加到文件中
hello
[root@lc133 ceshi]# cat 1.txt
nihao
hello
paste
paste工具用于合并文件行输出到屏幕,不会改动源文件
-d:自定义间隔符,默认是tab,只接受一个字符
-s:将每个文件中的所有内容按照一行输出,文件中的行与行以TAB间隔。
[root@lc133 ceshi]# cat 1.txt
nihao
hello
[root@lc133 ceshi]# cat 2.txt
world
[root@lc133 ceshi]# paste 1.txt 2.txt
nihao world
hello
[root@lc133 ceshi]# paste 2.txt 1.txt
world nihao
hello
[root@lc133 ceshi]# paste -d '*' 1.txt 2.txt
nihao*world
hello*
[root@lc133 ceshi]# paste -s -d '*' 1.txt 2.txt
nihao*hello
world
xargs 上一个命令的输出作为下一个命令的命令行参数
管道(|):上一个命令的输出作为下一个命令的输入,做的是数据源。
xargs 可以将管道或标准输入(stdin)数据转换成命令行参数,也能够从文件的输出中读取数据。
xargs 一般是和管道一起使用。
命令格式:
''[somecommand]|[filename]'' |xargs -item command
OPTIONS:
-a file 从文件中读入作为sdtin
-E flag flag必须是一个以空格分隔的标志,当xargs分析到含有flag这个标志的时候就停止。
-p 当每次执行一个argument的时候询问一次用户。
-n num 后面加次数,表示命令在执行的时候一次用的argument的个数,默认是用所有的。
-t 表示先打印命令,然后再执行。
-i 或者是-I,这得看linux支持了,将xargs的每项名称,一般是一行一行赋值给 {},可以用 {} 代替。
-r no-run-if-empty 当xargs的输入为空的时候则停止xargs,不用再去执行了。
-d delim 分隔符,默认的xargs分隔符是回车,argument的分隔符是空格,这里修改的是xargs的分隔符。
[root@lc133 ceshi]# cat 1.txt
nihao
hello
hello
[root@lc133 ceshi]# xargs -a 1.txt #默认行输出
nihao hello hello
[root@lc133 ceshi]# xargs -a 1.txt -E hello #读到hello时停止
nihao
[root@lc133 ceshi]# xargs -a 1.txt -p #-p询问用户
echo nihao hello hello ?...y
nihao hello hello
[root@lc133 ceshi]# xargs -a 1.txt -n1
nihao
hello
hello
[root@lc133 ceshi]# xargs -a 1.txt -t #显示输出命令然后执行不需要用户确认
echo nihao hello hello
nihao hello hello
shell字符
!: 执行历史命令 !! 执行上一条命令
$: 变量中取内容符
+ - * / %: 对应数学运算 加 减 乘 除 取余数
&: 后台执行
;: 分号可以在shell中一行执行多个命令,命令之间用分号分割
\: 转义字符
``: 反引号 命令中执行命令 echo "today is `date +%F`"
' ': 单引号,脚本中字符串要用单引号引起来,但是不同于双引号的是,单引号不解释变量
" ": 双引号,脚本中出现的字符串可以用双引号引起来
通配符
~: 家目录 # cd ~ 代表进入用户家目录
*: 星号是shell中的通配符 匹配所有
?: 问号是shell中的通配符 匹配除回车以外的一个字符
[list]: 匹配[list]中的任意单个字符
[!list]: 匹配除list中的任意单个字符
{string1,string2,...}: 匹配string1,string2或更多字符串
重定向
> 覆盖输入
>> 追加输入
< 输出
<< 追加输出
管道命令
|: 管道符 上一个命令的输出作为下一个命令的输入
echo命令主要用来显示字符串信息。
语法:echo [-ne][字符串]
补充说明:
1、echo会将输入的字符串送往标准输出。
2、输出的字符串间以空白字符隔开,并在最后加上换行号。
OPTIONS:
-n 不要在最后自动换行
-e 若字符串中出现以下字符,则特别加以处理,而不会将它当成一般文字输出:
转义字符
\a 发出警告声;
\b 删除前一个字符;
\t 插入tab;
\n 换行且光标移至行首;
\c 最后不加上换行符号;
\f 换行但光标仍旧停留在原来的位置;
\r 光标移至行首,但不换行;
\v 与\f相同;
\ 插入\字符;
\033或\e 设置终端属性,如字体颜色、背景颜色、定位光标等
echo -e "\033[1mOK" #加粗显示 OK后没关闭属性设置
echo -e "\e[1mOK\e[0m" #使用\e和\033的效果相同
echo -e "\e[4mOK\e[0m" #加下画线后输出 OK
echo -e "\e[5mOK\e[0m" #闪烁显示 OK
echo -e "\e[30mOK\e[0m" #黑色显示 OK
echo -e "\e[31mOK\e[0m" #红色显示 OK
echo -e "\e[32mOK\e[0m" #绿色显示 OK
echo -e "\e[33mOK\e[0m" #棕色显示 OK
echo -e "\e[34mOK\e[0m" #蓝色显示 OK
echo -e "\e[35mOK\e[0m" #紫色显示 OK
echo -e "\e[36mOK\e[0m" #蓝绿色显示 OK
echo -e "\e[37mOK\e[0m" #亮灰色显示 OK
echo -e "\e[1;33mOK\e[0m" #亮黄色显示 OK
echo -e "\e[42mOK\e[0m" #绿色背景显示 OK
echo -e "\e[44mOK\e[0m" #蓝色背景显示 OK
echo -e "\e[32;44mOK\e[0m" #绿色字体,蓝色背景显示 OK
字颜色:30—–37
echo -e “\033[30m 黑色字 \033[0m”
echo -e “\033[31m 红色字 \033[0m”
echo -e “\033[32m 绿色字 \033[0m”
echo -e “\033[33m 黄色字 \033[0m”
echo -e “\033[34m 蓝色字 \033[0m”
echo -e “\033[35m 紫色字 \033[0m”
echo -e “\033[36m 天蓝字 \033[0m”
echo -e “\033[37m 白色字 \033[0m”
字背景颜色范围:40—–47
echo -e “\033[40;37m 黑底白字 \033[0m”
echo -e “\033[41;37m 红底白字 \033[0m”
echo -e “\033[42;37m 绿底白字 \033[0m”
echo -e “\033[43;37m 黄底白字 \033[0m”
echo -e “\033[44;37m 蓝底白字 \033[0m”
echo -e “\033[45;37m 紫底白字 \033[0m”
echo -e “\033[46;37m 天蓝底白字 \033[0m”
echo -e “\033[47;30m 白底黑字 \033[0m”
最后面控制选项说明
\033[0m 关闭所有属性
\033[1m 设置高亮度
\033[4m 下划线
\033[5m 闪烁
\033[7m 反显
\033[8m 消隐
\033[30m — \33[37m
设置前景色
\033[40m — \33[47m 设置背景色
\033[nA 光标上移n行
\033[nB 光标下移n行
\033[nC 光标右移n行
\033[nD 光标左移n行
\033[y;xH设置光标位置
\033[2J 清屏
\033[K 清除从光标到行尾的内容
\33[s 保存光标位置
\033[u 恢复光标位置
\033[?25l 隐藏光标
\033[?25h 显示光标
printf 命令可以格式化输出数据。
printf [格式] 参数
备注:一般 printf 命令的参数就是需要输出的内容。
常用的格式字符串:
%d或%i 十进制整数
%o 八进制整数
%x 十六进制整数
%u 无符号十进制整数
%f 浮点数(小数点数)
%s 字符串
\b 退格键(Backspace)
\f 换行但光标仍停留在原来的位置
\n 换行且光标移至行首
\r 光标移至行首,但不换行
\t Tab键
默认不换行,右对齐
printf "%d" 12 #屏幕显示整数 12
printf "%5d" 12 #设置了打印宽度为 5,以右对齐的方式显示整数 12
printf "%-5d" 12 #左对齐
printf "|%10d|\n" 12 #右对齐输出 12,字符宽度为 10 ,\n换行
printf "%d\n" 011 #011前的0代表8进制,省略代表十进制,0x十六进制
printf "%f\n" 3.88 #打印小数
printf "%.3f\n" 3.88 #小数点后保留 3 位
printf "|%-8.3f|\n" 3.88 #左对齐,占用 8 位宽度
[root@lc133 ceshi]# printf "\e[32m%s\e[0m\n" "hello" #输出绿色hello
hello
read 命令读取用户的输入信息
语法:
read [选项] [变量名]
如果未指定变量名,则默认变量名称为 REPLY。
-p 显示提示信息
-t 设置读入数据的超时时间
-n 设置读取n个字符后结束,而默认会读取标准输入的一整行内容
-r 支持读取\,而默认read命令理解\为特殊符号(转义字符)
-s 静默模式,不显示标准输入的内容(Silent mode)
[root@lc133 ceshi]# read -p "a:"
a:123
[root@lc133 ceshi]# echo $REPLY
123
[root@lc133 ceshi]# read -p "a:" a
a:34
[root@lc133 ceshi]# echo $a
34
[root@lc133 ceshi]# read a
\abc
[root@lc133 ceshi]# echo $a #默认 read 命令不支持\
abc
[root@lc133 ceshi]# read -r a #设置 read 命令支持读取\
\abc
[root@lc133 ceshi]# echo $a
\abc
[root@lc133 ceshi]# read -s -p "请输入密码:" pass #让用户输入的任何数据都不显示
请输入密码:[root@lc133 ceshi]# echo $pass
123
正则表达式
基本正则表达式
字符 含义
c 匹配字母c
. 匹配任意单个字符
* 匹配前一个字符出现零次或多次
.* 匹配多个任意字符
[] 匹配集合中的任意单个字符,括号可以是任意数量字符的集合
[x-y] 匹配连续的字符串范围
^ 匹配字符串的开头
$ 匹配字符串的结尾
[^] 匹配否定,对括号中的集合取反
\ 匹配转义后的字符串
\{n,m\} 匹配前一个字符重复n到m次
\{n,\} 匹配前一个字符重复至少n次
\{n\} 匹配前一个字符重复n次
\(\) 将\(与\)之间的内容存储在“保留空间”,最多可存储9个
\n 通过\1至\9调用保留空间中的内容
扩展正则表达式
字符 含义
{n,m} 等同于基本正则表达式的\{n,m\}
+ 匹配前的字符出现一次或多次
? 匹配前的字符出现零次或一次
| 匹配逻辑或,即匹配|前或后的字串
() 匹配正则集合,同时也有保留的意思,等同于基本正则表达式的\(\)
字符集 含义
[:alpha:] 字母字符
[:alnum:] 字母与数字字符
[:cntrl:] 控制字符
[:digit:] 数字字符
[:xdigit:] 十六进制数字字符
[:punct:] 标点符号
[:graph:] 非空格字符
[:print:] 任意可以显示的字符
[:space:] 任意可以产生空白的字符
[:blank:] 空格与Tab键字符
[:lower:] 小写字符
[:upper:] 大写字符
shell介绍
shell是一个程序,采用C语言编写,是用户和linux内核沟通的桥梁。它既是一种命令语言,又是一种解释性的编程语言。解释性语言,程序不需要编译,程序在运行时由解释器翻译成机器语言,每执行一次都要翻译一次。因此效率比较低。
bash shell特性
Tab只能补全命令和文件
常见的快捷键
ctrl+c 终止前台运行的程序
ctrl+z 将前台运行的程序挂起到后台
ctrl+d 退出 等价exit
ctrl+l 清屏
ctrl+a |home 光标移到命令行的最前端
ctrl+e |end 光标移到命令行的后端
ctrl+u 删除光标前所有字符
ctrl+k 删除光标后所有字符
ctrl+r 搜索历史命令
shell脚本:将需要完成某个任务所执行的命令按照执行顺序保存到文本中,并给予执行权限。
脚本的命名;nginx_install.sh 脚本名称 脚本扩展名 .sh,名字不要太长 26个字节内.
shebang:
脚本第一行, #!魔法字符,指定脚本代码执行的程序。即它告诉系统这个脚本需要什么解释器来执行,也就是使用哪一种Shell
注释:#代表注释
脚本不加执行权限无法执行,可以使用shell解释器执行会忽略掉shebang,
[root@lc133 ceshi]# cat hello.sh
#!/bin/bash
#上面是魔法字符,shebang
#这是注释
#下面是具体内容
echo "hello"
[root@lc133 ceshi]# ./hello.sh
-bash: ./hello.sh: 权限不够
[root@lc133 ceshi]# bash hello.sh
hello
[root@lc133 ceshi]# chmod +x hello.sh
[root@lc133 ceshi]# ./hello.sh
hello
查看root用户默认的shell解释器
[root@lc133 ceshi]# cut -d: -f1,7 /etc/passwd | grep root
root:/bin/bash
[root@lc133 ceshi]# echo $SHELL
/bin/bash
查看当前机器支持的shell解释器
[root@lc133 ceshi]# cat /etc/shells
/bin/sh
/bin/bash
/usr/bin/sh
/usr/bin/bash
/bin/tcsh
/bin/csh
变量
系统中的变量根据作用域及生命周期可以分为四类:本地变量、环境变量、全局变量、内置变量
本地变量
用户自定义的变量,定义在脚本或者当前终端中,脚本执行完毕或终端结束变量失效。
定义变量:变量名=值
变量名命名规则:
命名只能使用英文字母,数字和下划线,首个字符不能以数字开头。
中间不能有空格,可以使用下划线(_)。
不能使用标点符号。
不能使用bash里的关键字(可用help命令查看保留关键字)。
注意:字符串要用单引号或双引号引起来
取消变量 unset
[root@lc133 ceshi]# gril="小芳"
[root@lc133 ceshi]# echo $gril
小芳
[root@lc133 ceshi]# unset gril
[root@lc133 ceshi]# echo $gril
[root@lc133 ceshi]#
有类型变量 declare
-i 将变量看成整数
-r 使变量只读 readonly,该变量的值无法改变,并且不能为unset
-x 标记变量通过环境导出 export
-a 指定为索引数组(普通数组);查看普通数组
-A 指定为关联数组;查看关联数组
[root@lc133 ceshi]# declare -i num='nihao'
[root@lc133 ceshi]# echo $num
0
[root@lc133 ceshi]# num=34
[root@lc133 ceshi]# echo $num
34
[root@lc133 ceshi]# declare -r num
[root@lc133 ceshi]# num=31
-bash: num: 只读变量
[root@lc133 ceshi]# unset num
-bash: unset: num: 无法反设定: 只读 variable
[root@lc133 ceshi]# declare -x
declare -x HISTCONTROL="ignoredups"
declare -x HISTSIZE="1000"
declare -x HOME="/root"
declare -x HOSTNAME="lc133"
declare -x KUBECONFIG="/etc/kubernetes/kubelet.conf"
declare -x LANG="zh_CN.UTF-8"
declare -x LESSOPEN="||/usr/bin/lesspipe.sh %s"
...
在当前shell终端中在开启一个子shell终端观察变量
[root@lc133 ceshi]# pstree
systemd─┬─ModemManager───2*[{ModemManager}]
...
├─sshd─┬─sshd───bash───pstree
│ └─sshd───sftp-server
....
[root@lc133 ceshi]# bash
[root@lc133 ceshi]# pstree
systemd─┬─ModemManager───2*[{ModemManager}]
...
├─sshd─┬─sshd───bash───bash───pstree
│ └─sshd───sftp-server
....
[root@lc133 ceshi]# echo $num #子shell中不存在num变量
[root@lc133 ceshi]# exit #退出子shell
exit
[root@lc133 ceshi]# echo $num #num变量存在父shell中
31
调用解释器执行脚本会开启一个子shell,脚本中的变量只存在子shell中,脚本执行结束,变量消失。
[root@lc133 ceshi]# cat hello.sh
#!/bin/bash
#上面是魔法字符,shebang
#这是注释
#下面是具体内容
boy="吴彦祖"
[root@lc133 ceshi]# bash hello.sh
[root@lc133 ceshi]# echo $boy
调用source或者. (点符号),在当前shell环境加载脚本,变量会被保存下来
[root@lc133 ceshi]# . hello.sh
[root@lc133 ceshi]# echo $boy
吴彦祖
环境变量
定义在用户家目录下的.bashrc或.bash_profile文件中,用户私有变量,只能本用户使用。用户个人配置变量,修改需要重新加载生效
~/.bashrc
~/.bash_profile
全局配置文件:
/etc/profile
/etc/bashrc
查询当前用户的所有变量(临时变量与环境变量) set
[root@lc133 ceshi]# set | grep boy
boy=吴彦祖
环境变量可以命令临时创建,永久生效需要改配置文件(变量追加到配置文件中)
[root@lc133 ceshi]# tail -1 /etc/profile
export KUBECONFIG=/etc/kubernetes/kubelet.conf
#profile 中追加了一条的KUBECONFIG的变量
查看当前用户的环境变量 env,将当前变量变成环境变量 export
[root@lc133 ceshi]# env | grep boy
[root@lc133 ceshi]# export boy
[root@lc133 ceshi]# env | grep boy
boy=吴彦祖
检查环境变量的命令
set 输出当前shell所有变量,包括全局变量,局部变量(注意父子shell)
env 只显示全局变量
declare 同set
export 显示和设置环境变量
撤销变量unset 变量名
设置只读变量 readonly同declare -r ,shell结束,只读变量失效
取出所有环境变量的名字,利用awk -F指定分割符,空格,等于号,打印第三行
[root@lc133 ceshi]# export | awk -F '[ :=]' '{print $3}'
HISTCONTROL
HISTSIZE
HOME
HOSTNAME
KUBECONFIG
LANG
LESSOPEN
LOGNAME
LS_COLORS
MAIL
OLDPWD
PATH
PWD
QTDIR
QTINC
QTLIB
QT_GRAPHICSSYSTEM_CHECKED
SHELL
SHLVL
SSH_CLIENT
SSH_CONNECTION
SSH_TTY
TERM
USER
XDG_DATA_DIRS
XDG_RUNTIME_DIR
XDG_SESSION_ID
boy
环境变量加载顺序
/etc/profile -> ~/.bash_profile -> ~/.bashrc -> /etc/bashrc -> ~/.bash_logout
后面的变量会覆盖前面顺序的变量
所以:当全局变量/etc/profile,与用户家目录下的.bash_profile,中变量冲突时,其他用户会输出全局变量配置的变量值,自己用户登录会输出家目录定义的变量值
全局变量
使用export命令将本地变量输出为当前shell中的环境变量
所有用户及shell都可以使用,可以在/etc/profile /etc/bashrc下永久定义
打印全局变量 printenv
内置变量
系统变量(内置bash中变量) : shell本身已经固定好了它的名字和作用.
UID 当前账户的账户ID号
USER 当前账户的账户名称
HISTSIZE 当前终端的最大历史命令条目数量(最多可以记录多少条历史命令)
HOME 当前账户的根目录
LANG 当前环境使用的语言
PATH 命令搜索路径
PWD 返回当前工作目录
RANDOM 随机返回0至32767的整数
参数变量:
$0 当前脚本的文件名。
$n 传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例 如,第一个参数是 $1,第二个参数是 $2
$# 传递给脚本或函数的参数个数。
$* 传递给脚本或函数的所有参数。获得的参数各自作为单个字符串, 当被 双引号" "包含时,然后作为一个整体
$@ 传递给脚本或函数的所有参数。获得的参数各自作为单个字符串, 当被 双引号" "包含时,然后获得的参数仍然各自作为单个字符串
$? 上个命令的退出状态,或函数的返回值,
若退出状态值为0,表示命令运行成功
若退出状态值为127,表示command not found
若退出状态值为126,表示找到了该命令但无法执行(权限不够)
若退出状态值为1&2,表示没有那个文件或目录
$$ 当前 Shell 进程 ID。对于 Shell 脚本,就是这些脚本所在的 进程 ID。
!$ 调用最后一条命令历史中的参数
!! 调用最后一条命令历史
状态变量:
$$ 获取当前shell的进程号(pid)
$! 执行上一个指令的pid,上一个后台运行进程的进程号
$? 获取执行上一个指令的返回值(0为成功,非零为失败)
$_ 在此之前执行的命令(上一个命令)或脚本的最后一个参数
举个栗子:
[root@lc133 ceshi]# cat hello.sh
#!/bin/bash
#上面是魔法字符,shebang
#这是注释
#下面是具体内容
echo "我的脚本名字是:$0"
echo "我最喜欢的人是:$1"
echo "传递的个数是:$#"
echo "当前的进程号:$$"
[root@lc133 ceshi]# bash hello.sh "刘亦菲"
我的脚本名字是:hello.sh
我最喜欢的人是:刘亦菲
传递的个数是:1
当前的进程号:6205
[root@lc133 ceshi]# echo $?
0
[root@lc133 ceshi]# bash hello.sh "刘亦菲"
我的脚本名字是:hello.sh
我最喜欢的人是:刘亦菲
传递的个数是:1
当前的进程号:6230
[root@lc133 ceshi]# !!
bash hello.sh "刘亦菲"
我的脚本名字是:hello.sh
我最喜欢的人是:刘亦菲
传递的个数是:1
当前的进程号:6231
[root@lc133 ceshi]# bash hello.sh !$
bash hello.sh "刘亦菲"
我的脚本名字是:hello.sh
我最喜欢的人是:刘亦菲
传递的个数是:1
当前的进程号:6262
∗ 和 *和 ∗和@的区别
$* :表示将变量看成一个整体
$@ :表示变量是独立的
利用for循环看区别
[root@lc133 ceshi]# cat dif.sh
#!/bin/bash
echo "这是“\$*”"
for i in "$*"
do
echo "$i"
done
echo "这是“\$@”"
for i in "$@"
do
echo "$i"
done
[root@lc133 ceshi]# bash dif.sh 1 2 3 4
这是“$*”
1 2 3 4
这是“$@”
1
2
3
4
$?状态码
[root@lc133 ceshi]# cat hello.sh
#!/bin/bash
#上面是魔法字符,shebang
#这是注释
#下面是具体内容
[ $# -ne 2 ] && {
#判断输入参数个数是否不等于2
echo "must be two args"
exit 119
#终止程序,返回119状态码,提供给当前shell的$?变量,若是函数里可以用return 119
}
[root@lc133 ceshi]# bash hello.sh 1
must be two args
[root@lc133 ceshi]# $?
bash: 119: 未找到命令...
小结:
本地变量:当前用户自定义的变量。当前进程中有效,其他进程及当前进程的子进程无效。
环境变量:当前进程有效,并且能够被子进程调用。
全局变量:全局所有的用户和程序都能调用,且继承,新建的用户也默认能调用.
内置变量:shell本身已经固定好了它的名字和作用.
变量类型 | 作用域 | 生命周期 |
---|---|---|
本地变量 | 当前shell环境(子shell不能用) | 脚本结束或终端结束 |
环境变量 | 当前shell或者子shell | 当前进程结束 |
全局变量 | 所有用户及shell环境 | 关机 |
内置变量 | 所有用户及shell环境 | 关机 |
shell内置命令与外置命令
内置命令:在系统启动时就加载入内存,常驻内存,执行效率高,但是占用资源。
外置命令:系统需要从硬盘中读取程序文件,在读入内存加载,外置命令一定会开启子进程执行.
通过type命令,验证是否内置、外置命令
[root@lc133 ceshi]# type whoami
whoami 是 /usr/bin/whoami
[root@lc133 ceshi]# type echo
echo 是 shell 内嵌
[root@lc133 ceshi]# type which
which 是 `alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde' 的别名
[root@lc133 ceshi]# type yum
yum 是 /usr/bin/yum
[root@lc133 ceshi]#
通过compgen -b命令,查看内置命令
[root@lc133 ceshi]# compgen -b
shell参数与变量替换(parameter and variable expansion)
字符串切割与掐头去尾
${变量:偏移量} 从变量的偏移量位置开始,切割截取变量的值到结尾。 变量的偏移量起始值为0
${变量:偏移量:长度} 从变量的偏移量位置开始,截取特定长度的变量值。 变量的偏移量起始值为0
${变量#关键字} 使用关键字对变量进行模式匹配,从左往右删除匹配到的内容,关键字可以使用*符号,使用#匹配时为最短匹配(最短匹配掐头)
${变量##关键字} 使用关键字对变量进行模式匹配,从左往右删除匹配到的内容,关键字可以使用*符号,使用##匹配时为最长匹配(最长匹配掐头)
${变量%关键字} 使用关键字对变量进行模式匹配,从右往左删除匹配到的内容,关键字可以使用*符号,使用%匹配时为最短匹配(最短匹配去尾)
${变量%%关键字} 使用关键字对变量进行模式匹配,从右往左删除匹配到的内容,关键字可以使用*符号,使用%%匹配时为最长匹配(最长匹配去尾
变量内容的统计与替换
${!前缀字符*} 查找以指定字符开头的变量名称,变量名之间使用IFS分隔
${!前缀字符@} 查找以指定字符开头的变量名称,@在引号中将被扩展为独立的单词
${!数组名称[*]} 列出数组中所有下标,*在引号中会被扩展为一个整体
${!数组名称[@]} 列出数组中所有下标,@在引号中会被扩展为独立的单词
${#变量} 统计变量的长度,变量可以是数组
${变量/旧字符串/新字符串} 将变量中的旧字符串替换为新字符串,仅替换第一个
${变量//旧字符串/新字符串} 将变量中的旧字符串替换为新字符串,替换所有
${变量^匹配字符} 将变量中的小写替换为大写,仅替换第一个
${变量^^匹配字符} 将变量中的小写替换为大写,替换所有
${变量,匹配字符} 将变量中的大写替换为小写,仅替换第一个
${变量,,匹配字符} 将变量中的大写替换为小写,替换所有
这几种对变量的替换方式,都不会改变变量自身的值
利用替换修改文件名,xiaohong替换成xioaming
[root@lc133 ceshi]# touch xiaohong{1..5}.txt
[root@lc133 ceshi]# ls *.txt
xiaohong1.txt xiaohong2.txt xiaohong3.txt xiaohong4.txt xiaohong5.txt
[root@lc133 ceshi]# for file_name in `ls *.txt` ; do mv $file_name `echo ${file_name//hong/ming}` ; done
[root@lc133 ceshi]# ls *.txt
xiaoming1.txt xiaoming2.txt xiaoming3.txt xiaoming4.txt xiaoming5.txt
变量测试
${变量:-关键字} 如果变量未定义或值为空,则返回关键字。否则,返回变量的值
${变量:=关键字} 如果变量未定义或值为空,则将关键字赋值给变量,并返回结果。否则,
直接返回变量的值
${变量:?关键字} 如果变量未定义或值为空,则通过标准错误显示包含关键字的错误信息。
否则,直接返回变量的值
${变量:+关键字} 如果变量未定义或值为空,就直接返回空。否则,返回关键字
shell花括号扩展(brace expansion)
**花括号扩展不可以使用引号 **
[root@lc133 ceshi]# echo {1,2}
1 2
[root@lc133 ceshi]# echo {xiaoming,xiaohong}
xiaoming xiaohong
[root@lc133 ceshi]# echo {1..10}
1 2 3 4 5 6 7 8 9 10
[root@lc133 ceshi]# echo {1..10..2}
1 3 5 7 9
[root@lc133 ceshi]# echo {a..z..4} #a 至 z,步长为 4
a e i m q u y
花括号扩展支持嵌套
[root@lc133 aaa]# echo a{1,2}b
a1b a2b
[root@lc133 aaa]# echo a{1,2{1,2}}b
a1b a21b a22b
Shell 解释器的属性与初始化命令行终端
set命令可以通过选项开启或关闭特定的 Bash 属性.
shopt 命令可以通过-s 和-u 开启或关闭某 些 Bash 属性。
常用set命令属性
语法:set 选项
属性 set选项 功能描述
allexport [+-]a 将函数和变量传递给子进程(默认关闭)
braceexpand [+-]B 支持花括号扩展(默认开启)
errexit [+-]e 当命令返回非0值时立刻退出(默认关闭)
hashall [+-]h 将该命令位置保存到Hash表(默认开启)
histexpand [+-]H 支持使用!对历史命令进行扩展替换(默认开启)
noclobber [+-]C Bash使用重定向操作符>、>&和<>时,不会覆盖已存在的文件,可以使用>|绕过该限制(默认关闭)
noexec [+-]n 仅读取命令,不执行命令,仅在脚本中有效(默认关闭)
nounset [+-]u 变量进行扩展替换时如果变量未定义,则报错(默认关闭)
shopt命令支持的常用属性及其功能
语法:
shopt -s(-u) 属性
属性 功能描述
cdable_vars 内建命令 cd 的参数如果不是目录,就假定其是一个变量
cdspell cd命令中目录的拼写错误可以简单自动纠正
checkhash 根据hash记录找不到程序时继续使用其他方式查找程序路径
cmdhist 将一个多行命令的历史记录保存到一行中(默认开启)
extglob 允许在路径替换时使用扩展模式匹配
nocaseglob 当进行路径扩展时不区分大小写(默认关闭)
nocasematch 当使用case和[[进行模式匹配时不区分大小写(默认关闭)
举例shopt
[root@centos7 ~]# hello=/etc #定义变量
[root@centos7 ~]# cd hello #没有 hello 目录,报错
-bash: cd: hello: No such file or directory
[root@centos7 ~]# shopt -s cdable_vars #开启 cdable_vars 属性
[root@centos7 ~]# cd hello #没有 hello 目录,但进入
/etc
/etc
[root@centos7 ~]# shopt -u cdable_vars #关闭 cdable_vars 属性
[root@centos7 ~]# cd /ect #拼写错误,命令无法执行
-bash: cd: /ect: No such file or directory
[root@centos7 ~]# shopt -s cdspell #开启自动纠错属性
[root@centos7 ~]# cd /ect #拼写错误依然可以执行
/etc
[root@centos7 etc]# cd /etcc #拼写错误依然可以执行
/etc
[root@centos7 etc]# cd /ettc
/etc
[root@centos7 etc]# cd /ettcc #但是无法改正所有错误
-bash: cd: /ettcc: No such file or directory
shell中的数值运算
常用的运算符
运算符号 含义描述
++ 自加1
-- 自减1
+ 加法
- 减法
* 乘法
/ 除法
** 求幂
% 取余(求模)
+= 自加任意数
-= 自减任意数
*= 自乘任意数
/= 自除任意数
%= 对任意数取余
&& 逻辑与
|| 逻辑或
> 大于
>= 大于或等于
< 小于
<= 小于或等于
表达式?表达式:表达式 根据表达式的结果,返回特定的值
常用的运算命令
运算操作符/运算命令 说明
(()) 用于整数运算,效率很高
let 用于整数运算,和(())类似
$[] 用于整数运算
expr 可用于整数运算,也可以处理字符串。
bc Linux下的一个计算器程序,可以处理整数和小数。
declare 定义变量的值和属性,-i参数可以定义整形变量,做运算
双(())
运算操作符与运算命令 说明
((i=i+1)) 此种书写方法为运算后赋值法,即将i+l 的运算结果赋值给变量i。注不能用echo ((i+ 1))的形式输出表达式的值,但可以用echo $((i=i+l))输出其值.
i=$((i+ l)) 可以在“(())”前加$符.表示将表达式运算后赋值给i
((8>7&&5=5)) 可以进行比较操作,还可以加入逻辑与和逻辑或,用于条件判断
echo $((2+ l)) 需要直接输出运算表达式的运算结果时,可以在(())前加$符
[root@lc133 aaa]# ((i=2+3))
[root@lc133 aaa]# echo $i
5
[root@lc133 aaa]# ((a=1+2,b=7+8))
[root@lc133 aaa]# echo $a $b
3 15
[root@lc133 aaa]# echo $((a+b))
18
[root@lc133 aaa]# echo $((2+3+3))
8
let命令
bash解释器中不能直接a+b这种变量的加减
[root@lc133 aaa]# let c=a+b
[root@lc133 aaa]# echo $c
18
expr
ARG1 | ARG2 若ARG1 的值不为0 或者为空,则返回ARG1,否则返回ARG2
ARG1 & ARG2 若两边的值都不为0 或为空,则返回ARG1,否则返回 0
ARG1 < ARG2 ARG1 小于ARG2
ARG1 <= ARG2 ARG1 小于或等于ARG2
ARG1 = ARG2 ARG1 等于ARG2
ARG1 != ARG2 ARG1 不等于ARG2
ARG1 >= ARG2 ARG1 大于或等于ARG2
ARG1 > ARG2 ARG1 大于ARG2
ARG1 + ARG2 计算 ARG1 与ARG2 相加之和
ARG1 - ARG2 计算 ARG1 与ARG2 相减之差
ARG1 * ARG2 计算 ARG1 与ARG2 相乘之积
ARG1 / ARG2 计算 ARG1 与ARG2 相除之商
ARG1 % ARG2 计算 ARG1 与ARG2 相除之余数
字符串 : 表达式 定位字符串中匹配表达式的模式
match 字符串 表达式 等于"字符串 :表达式"
substr 字符串 偏移量 长度 替换字符串的子串,偏移的数值从 1 起计
index 字符串 字符 在字符串中发现字符的地方建立下标,或者标0
length 字符串 字符串的长度
+ 记号 将给定记号解析为字符串,即使它是一个类似
“match”或运算符"/"那样的关键字
( 表达式 ) 给定<表达式>的值
[root@lc133 aaa]# expr 1 + 2
3
[root@lc133 aaa]# expr 1 \> 2 #注意需要转义字符
0
[root@lc133 aaa]# expr 19 \* 2
38
[root@lc133 aaa]# expr "nihao" : "..hao"
5
[root@lc133 aaa]# expr "nihao" : "ni"
2
[root@lc133 aaa]# expr length 1234567
7
[root@lc133 aaa]# expr substr "nihao" 1 1
n
[root@lc133 aaa]# expr substr "nihao" 2 1
i
bc
bc(选项)(参数)
-i:强制进入交互式模式;退出交互模式
-l:定义使用的标准数学库
-w:对POSIX bc的扩展给出警告信息;
-q:不打印正常的GNU bc环境信息;
-v:显示指令版本信息;
-h:显示指令的帮助信息。
[root@lc133 ~]# bc -i
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'.
7+8
15
8-9
-1
9*1.1
9.9
quit
与|结合,默认无小数,scale=2设小数位,2 代表保留两位
[root@lc133 ~]# a=5
[root@lc133 ~]# num=$(echo "$a*4" | bc)
[root@lc133 ~]# echo $num
20
[root@lc133 ~]# echo "10^10" | bc
10000000000
[root@lc133 ~]# echo "10^2" | bc
100
[root@lc133 ~]# echo "sqrt(100)" | bc
10
[root@lc133 ~]# echo "5/2" | bc
2
[root@lc133 ~]# echo "scale=2;5/2" | bc
2.50
进制转换
默认输入十进制,输出十进制,ibase和obase改变输入输出属性
[root@lc133 ~]# echo "ibase=8;10" | bc
8
[root@lc133 ~]# echo "obase=8;10" | bc
12
[root@lc133 ~]# echo "obase=16;10" | bc
A
[root@lc133 ~]# echo "obase=16;ibase=2;11111111" | bc
FF
[root@lc133 ~]# echo "obase=10;ibase=8;11111111" | bc
2396745
条件测试
条件测试语法
test <测试表达式> 这是利test 命令进行条件测试表达式的方法。test 命令和“〈测试表达式〉”之间至少有一个空格。
[ <测试表达式> ] 这是通过[](单中括号)进行条件测试表达式的方法,和test 命令的用法相同,边界和内容之间至少有一个空格。
[[ <测试表达式> ]] 这是通过[[]](双中括号)进行条件测试表达式的方法,是比test 和[]更新的语法格式。[[]]的边界和内容之间至少有一个空格。
((<测试表达式>)) 这是通过(())(双小括号)进行条件测试表达式的方法,一般用于if 语句里。(())(双小括号)两端不需要有空格。
test命令评估一个表达式,它的结果是真那么命令执行的状态码结果就是0,否则不为0,通过$?
取值。
多数情况下[]和[[]]是可以通用的,两者的主要差异是:test 或[]是符合POSIX 标准的测试语句,兼容性更强,几乎可以运行在所有Shell 解释器中,相比较而言[[]]仅可运行在特定的几个Shell 解释器中(如Bash、Zsh 等)。使用[[]]进行测试判断时可以使用正则表达式。使用数学比较符需要添加转义符号。
逻辑判断
在[]和test 中使用的操作符 在[[]]和(())中使用的操作符 说明
-a && and ,与,一假全假,全真为真
-o || or,或,一真全真,全假为假
! ! not,非,取反
整数的比较运算符
符号 含义
-eq 等于(equal)
-ne 不等于(not equal)
-gt 大于(greater than)
-ge 大于或等于(greater than or equal)
-lt 小于(less than)
-le 小于或等于(less or equal)
[root@lc133 ~]# test 3 -eq 3
[root@lc133 ~]# echo $?
0
[root@lc133 ~]# test 3 -eq 4
[root@lc133 ~]# echo $?
1
[root@lc133 ~]# [ 2 -ne 3 ] && echo y || echo n
y
[root@lc133 ~]# test 2 -gt 3 && echo y || echo n
n
[root@lc133 ~]# [[ 4 -ge 3 ]] && echo y || echo n
y
[root@lc133 ~]# if ((5 == 90)) ;then echo y; else echo n ;fi
n
[root@lc133 ~]# if ((5 < 90)) ;then echo y; else echo n ;fi
y
[root@lc133 ~]# if ((5 != 90)) ;then echo y; else echo n ;fi
y
字符串测试比较符
-n "字符串" 字符串的长度不为0 则为真, 即测试表达式成立,n可以理解为no zero
-z "字符串" 字符串的长度为0 则为真, 即测试表达式成立,z可以理解为zero
"字符串" ="字符串" 字符串相等则为真,测试表达式成立,可使用“==”代替“=”
"字符串" !="字符串" 字符串不相等则为真,测试表达式成立,不可使用“!==”代替“!=”
文件属性的判断与比较
-e file 判断文件或目录是否存在,存在返回真,否则返回假
-f file 判断存在且为普通文件
-d file 判断存在且为目录
-b file 判断存在且为块设备文件(如磁盘,U盘等设备)
-c file 判断存在且为字符设备文件(如键盘、鼠标等设备)
-L file 判断存在且为软链接文件
-p file 判断存在且为命名管道
-r file 判断存在且当前用户对该文件具有可读权限
-w file 判断存在且当前用户对该文件具有可写权限
-x file 判断存在且当前用户对该文件具有可执行权限
-s file 判断存在且文件大小非空
file1 -ef file2 两个文件使用相同设备、相同inode编号(硬链接),则返回真,否则返回假
file1 -nt file2 file1比file2更新1时返回真;或者file1存在而file2不存在时返回真
file1 -ot file2 file1比file2更旧时返回真;或者file2存在而file1不存在时返回真
函数
语法一:
函数名 () {
代码块
return N
}
语法二:
function 函数名 {
代码块
return N
}
函数中return说明:
1.return可以结束一个函数,类似于前面讲的循环控制语句break(结束当前循环,执行循环体后面的代码)
2.return默认返回函数中最后一个命令的退出状态,也可以给定参数值,该参数值的范围是0-256之间。
3.如果没有return命令,函数将返回最后一个Shell的退出值。
if语法
单if
if [ condition ] #condition 值为true or false
then #条件为真的时候执行
commands #代码块 一行或者多行代码
fi #语句的结束
if…eles
if [ condition ]
then #条件为真
commands1 #真 要执行代码块
else #条件为假
commands2 #假 要执行的代码块
fi #结束
if…elif…else
if [ condition 1] #满足第一个条件
then #真
command1 #执行command1代码块
elif [ condition 2] #满足第二个条件
then #真
commands2 #执行command2代码块
.......
else #如果条件都不满足
commandsX #执行commandX代码块
fi #结束判断
for循环
for variable_name in {list}
do
command
command
…
done
或者
for variable in a b c
do
command
command
done
while循环
while [ 表达式 ]
do
command...
done
while [ 1 -eq 1 ] 或者 (( 1 > 2 ))
do
command
command
...
done
until 和select 循环
until 条件判断
do
命令序列
done
与while 语句相反,until 循环语句只有当条件判断结果为真时才退出循环,而当条件判断结果为假时则执行循环体中的命令。
select 变量名 in 值列表
do
命令序列
Done
[root@lc133 ceshi]# cat hello.sh
#!/bin/bash
echo "请根据提示选择一个选项"
select item in "time" "ip" "mem" "exit"
do
case $item in
"time")
date;;
"ip")
ifconfig | grep inet;;
"mem")
free;;
"exit")
exit;;
*)
echo error;;
esac
done
[root@lc133 ceshi]# bash hello.sh
请根据提示选择一个选项
1) time
2) ip
3) mem
4) exit
#? 2
inet 192.168.145.133 netmask 255.255.255.0 broadcast 192.168.145.255
inet 127.0.0.1 netmask 255.0.0.0
inet 192.168.122.1 netmask 255.255.255.0 broadcast 192.168.122.255
#? 7
error
#? 4