shell进阶
shell 中的高级用法
1.if
单重判断
if cmd; then
cmd
cmd
cmd
fi
多重判断
单分支
if cmd;then
cmd
elif
cmd
fi
双分支
if cmd; then
cmd
elif cmd;then
cmd
elif cmd;then
cmd
else
cmd
fi
用于当判断条件的参数
逻辑判断
-a && 与
-o || 或
! 非
=~ 左边变量 ,右边扩展的正则表达式,不能写双引号
-z 判空
== 相等
!= 不相等
大小判断
-eq //等于
-ne //不等于
-gt //大于 (greater )
-lt //小于 (less)
-ge //大于等于
-le //小于等于
文件比较符
-e 判断对象是否存在
-d 判断对象是否存在,并且为目录
-f 判断对象是否存在,并且为常规文件
-L 判断对象是否存在,并且为符号链接
-h 判断对象是否存在,并且为软链接
-s 判断对象是否存在,并且长度不为0
-r 判断对象是否存在,并且可读
-w 判断对象是否存在,并且可写
-x 判断对象是否存在,并且可执行
-O 判断对象是否存在,并且属于当前用户
-G 判断对象是否存在,并且属于当前用户组
-nt 判断file1是否比file2新 [ ``"/data/file1"
-nt ``"/data/file2"
]
-ot 判断file1是否比file2旧 [ ``"/data/file1"
-ot ``"/data/file2"
]
2.case
要注意的是case 中使用的是引用变量,而不是声明变量名,$xxx
case支持glob风格的通配符:
*: 任意长度任意字符
?: 任意单个字符
[]:指定范围内的任意单个字符
a|b: a或b
case $num 变量引用 in
1|2|3) 判断条件 ,可以使用通配符
cmd1;
;; 根据;;来结束一个case段
4|5|6)
cmd2;
;;
*)
cmd3;
;;
esac
echo $passwd | passwd stdin user 设置用户密码
3.for
for 变量名(不是变量引用,不带$) in 列表;do
循环体
done
实例
for num in {1..10};do
echo num is $num;
done
列表生成方式:
- 直接给出列表
- 整数列表:
(a) {start..end}
(b) $(seq [start [step]] end) - 返回列表的命令
$(COMMAND) - 使用glob,如:*.sh
- 变量引用;$@, $*
列表可以用任意的合集,用命令解析得到的合集也可以,比如填 ls /bin,支持通配符
{1..100..3} 1到100,每次步进3
unset sum 删除变量sum,防止影响
for中使用多行重定向的话 。需要把第一个EOF加- 或者把EOF结尾标志顶格。否则无法识别
for i in {1..10};do
cat >>f1<<-EOF
ASDASD
ASDASD
EOF
done
或者
for i in {1..10};do
cat >>f1 <<EOF
ASDASD
ASDASD
EOF
done
4.for循环的第二种格式语法
sum=0
for ((i=1;i<=100;i++))
let sum+=i
done
for i in {1..3};do
for j in {1..10};do
if [ \(j -eq 5 ];then continue 2;fi
echo j=\)j
done
done
这边就表示,当j等于5的时候,跳出第二层循环 。不是j循环的第二次,而是第二层!!!就是跳出i循环的当次循环,直接执行i的下次循环
5.参数移除
shift n
shift[n] 参数左移,n可以指定具体数字,表示每次抛弃的参数个数
比如 1 2 3
就会先处理完1,然后把1抛弃,处理2,以此类推
6.并行执行
并行执行 把所有语句用 {} 包裹,最后加上 & 就是把语句放在后台并行执行。
wait 脚本执行完成后自动退出,不需要用户按回车
为什么会输出两次192.168.30.1
let命令特性点:如果他操作的变量值为 0 返回的是假,
如果变量非0,返回是真
比如 i=0
leti++ ,那么这一次返回的是0
unset i
let i++
echo $? 为 假 1
unset i
let ++i
echo $? 为真 0
n=10;seq 1 \(n 这样用这个,
n=10;echo {1..\)n} 这样是会报错的,不能这样执行
n=10;eval echo {1..$n} eval 会扫描并替换变量,然后执行该语句
用花括号分割变量
比如 \(ix\)j ,可能后面的\(j会识别成x\)j
写成
\(ix\){j} 即可
openssl rand -base64 20 | tr -dc '[: alpha :]'|head -c8
$[ 这样的格式里面可以做运算操作 ]
while 条件;do
循环体
done
: 返回真 等同于 true
selinux
用pgrep 查看进程是否存在,然后监控
pgrep 可以匹配到返回是true(0),而匹配不到会返回false(1)
向进程发送0信号,可以检测进程是否存在,因为0 信号不会对进程进行任何处理,但是会检查错误。
until 条件;do
循环体
done
与while相反,条件为假时进入循环,条件为真时,退出
who |grep USERNAME 查看该用户是否登录
7.while
while cmd;do
cmd
if cmd;then
continue 跳过当次执行
fi
done
while cmd;do
cmd
if cmd;then
break 退出当前循环块
fi
done
continue 和 break 后面可以跟数字,用于结束第N层的循环。
最里面的循环是第一层,往外层递增
whlie read line;do
循环体
done
while循环的特殊用法(遍历文件的每一行):
while read line; do
循环体
done < /PATH/FROM/SOMEFILE
依次读取/PATH/FROM/SOMEFILE文件中的每一行,且将行赋值给变量line
df | while read line;do
处理df的每一行,支持管道
done
8.until 循环
until cmd;do
循环体
done
进入条件:cmd为假
退出条件:cmd为真
本质就是一个跟while相反的条件判断
9.select 创建菜单
PS3="Please choose the menu 1-4 : " 修改运行脚本时候的select提示符
select variable in list
do
循环体命令
done
$REPLAY存储用户手动输入的内容
自动将List转换为菜单,根据选择的项,给变量赋值
PS1命令行提示符
PS2多行重定向提示符
PS3 select 命令提示符
select 是个无限循环,因此要记住用 break 命令退出循环,或用 exit 命令终止脚本。也可以按 ctrl+c 退出循环
select 经常和 case 联合使用
与 for 循环类似,可以省略 in list,此时使用位置参量
下面是一个简单的示例:
#!/bin/bash
echo "What is your favourite OS?"
select var in "Linux" "Gnu Hurd" "Free BSD" "Other"; do
break;
done
echo "You have selected $var"
</pre>
该脚本的运行结果如下:
What is your favourite OS?
1) Linux
2) Gnu Hurd
3) Free BSD
4) Other
#? 1
You have selected Linux</pre>
10.trap 捕获信号
trap 'echo press ctrl+c' int 捕获Int信号 ,转换为echo press ctrl +c
trap '' # 捕获信号,并且什么都不做,相当于拦截信号
trap '-' # 使信号恢复,恢复原信号的操作
可以捕捉15信号,使程序不可以正常关闭。但是无法捕捉9这个强制关闭的信号
脚本任务
alias.sh 配置别名
vim.sh 配置vim
yum.sh 配置yum
pack.sh 安装软件包
declare -f func4 查询是否存在func4函数
如果要在脚本里执行rm相关操作,需要检查对应的路径是否正确,变量是否赋值成功
11.函数
定义格式
语法一:
f_name ()
{
...函数体...
}
语法二:
function f_name
{
...函数体...
}
语法三:
function f_name ()
{
...函数体...
}
函数的优先级比别名高
函数的生效范围是当前shell
local 改变变量的有效范围,让他只在该函数内有效
全局变量 > 普通变量 > local 变量
declare 声明的变量,也是local 类型的
declare -ig num=100 加g之后定义,变量就变成了普通变量,不再是local变量
return 退出函数本身
在函数中使用echo 输出变量 ,就可以把输出写在if中直接判断
version (){ echo 1 }
if [ version
-eq 1 ] 判断是成立的
add() { echo $[$1+$2] }
add 1 2
输出3
函数复用
把函数保存为bash脚本,
新的脚本中使用
source functions (脚本名),相当于引用该脚本
之后就可以使用该脚本中的函数
action "commadn successful " 可以显示成功
action "xxx" /bin/false 表示失败
action "xxx /bin/true 表示成功
/etc/init.d/functions 储存了系统内置的函数
函数可以覆盖定义
export -f func1 将函数声明为全局函数,让子shell也可以使用该函数,定义函数的时候,不可以使用export
函数递归调用的时候,只有递归结束的时候,才会执行递归后的操作。
数组
关联索引 把数组的索引设置为自定义的格式,而不仅仅是数字
bash的数组支持稀疏索引(索引不连续),比如0,1, 3 有东西,2 没有 那么数组长度是3 ,但是他们不是连接的。输出2的话是空
declare -a ARRAY_NAME 普通数组
declare -A ARRAY_NAME 关联数组 必须先声明再使用
${a[1]}
echo ${name[* ]}
echo ${name[@]}
都代表输出数组中的所有元素
number=({1..10}) 这样也可以定义数组,()中存放任意生成多个字符串的命令都可以。通配符,正则表达式查找,bash命令,都能放
read -a title a b c 定义数组title ,内容是a b c
echo a b c | read -a s 定义数组s,内容是a b c (这样是错误的!!管理是不支持交互式赋值的)
关联数组一定要先定义再使用,否则数组变量会出问题
关联数组更像一个字典
${#name[* ]} 显示name数组的数组长度
因为使用了管道,所以开启了子shell,导致变量没有值
这样的话,在循环中使用的数组,声明周期单独只在循环中生效,因为这个时候while read line 使用的是开启的子shell
字符串处理
${var#*word}
str没有配置 表示变量不存在,没有声明
生成随机文件名
mktemp /data/tmpXXXXX 表示有五位的随机字符
expect
自动处理交互式命令,需要安装yum 包
自动传输文件
!/usr/bin/expect
spawn scp /etc/fstab 192.168.8.100:/app
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send “magedu\n" }
}
expect eof
spawn 表示捕获该命令 ,通过expect 来提交信息。当复制命令遇到yes或者no,就自动提交yes,然后继续执行。
当遇到password ,提交magedu
/etc/ssh/sshd_config
GSSAPIAuthentication no 关闭代理 79行
USEDNS NO 启动 115行
修改完成后 执行 systemctl sshd restart 重启sshd服务
加速sshd访问速度
自动登录
!/usr/bin/expect
spawn ssh 192.168.8.100
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send “magedu\n" }
}
interact
expect eof
interact 表示开启交互式
expect eof 结束expect 捕获
interact 搭配 #expect eof 表示登录终端后,释放对ssh的控制,这样expect就不会再继续捕获命令
expect 写一个控制脚本
用bash调用该脚本,做批量机器处理
矩阵转换
vim matrix.sh
#!/bin/bash
arr=([00]=1 [01]=2 [02]=3 [10]=4 [11]=5 [12]=6 [20]=7 [21]=8 [22]=9)
size=3
showmatrix () {
for ((i=0;i<size;i++));do
for ((j=0;j<size;j++));do
echo -e "${arr[$i$j]} \c"
done
echo
done
}
echo "Before convert"
showmatrix
for ((i=0;i<size;i++));do
for ((j=i;j<size;j++));do
if [ $i -ne $j ];then
temp=${arr[$i$j]}
arr[$i$j]=${arr[$j$i]}
arr[$j$i]=$temp
fi
done
done
echo "After convert"
shell进阶的更多相关文章
- 自学linux——12.shell进阶
Shell进阶 当把在Windows中写好的脚本传到linux中使用时,在Windows下每一行结尾是\n\r,而Linux下则是\n,所以会多出来\r,在linux中运行脚本时,需执行: sed - ...
- shell进阶教程
背景:就自己常用的shell脚本写作风格,总结了一些知识点.也是作为交接工作的一部分文档.部分内容单独写 #!/bin/sh # shell脚本进阶教程 # 1.常用知识点:变量设置/日期设置/格式化 ...
- Shell进阶精品课程
课程链接 Shell精品进阶教程:理解Shell的方方面面 课程目标 系统性的掌握shell相关知识,进阶shell脚本能力,对shell各方面了然于心 适用人群 具备shell基础但想深入.系统性掌 ...
- [SHELL进阶] (转)最牛B的 Linux Shell 命令 (四)
1.查看ASCII码表 man 7 ascii 很多人初学编程都会接触到ascii码的概念,有时候为了查某个符号的ascii值,可能还得翻箱倒柜找出当年的课本?Linux Manpage里面其实包含 ...
- [SHELL进阶] (转)最牛B的 Linux Shell 命令 (三)
1. 更友好的显示当前挂载的文件系统 mount | column -t 这条命令适用于任何文件系统,column 用于把输出结果进行列表格式化操作,这里最主要的目的是让大家熟悉一下 columnt ...
- [SHELL进阶] (转)最牛B的 Linux Shell 命令 (二)
1.用你最喜欢的编辑器来敲命令 command <CTRL-x CTRL-e> 在已经敲完的命令后按 <CTRL-x CTRL-e> ,会打开一个你指定的编辑器(比如vim,通 ...
- linux shell 进阶篇、shell脚本编程-创建函数
使用函数 #!/bin/bash # testing the script function myfun { echo "This is an example of a function&q ...
- shell进阶函数
函数的定义和用途 函数function是由若干条shell命令组成的语句块,实现shell代码的重用和模块化编程. 函数和shell程序的异同点 它与shell程序形式上是相似的,不同的是它不是一个单 ...
- [shell进阶]——shell多线程
关于shell的多线程 1. 多线程并发执行任务,而不用一台台的串行执行,能更快更高效 2. Shell并没有多线程的概念,所以: * 一般使用wait.read等命令技巧性地模拟多线程实 * 使用命 ...
- shell 进阶之匹配字符串
一,操作字符串 1,字符串长度 expr 命令取字符串函数 自带shell函数读取 2,匹配字符串开头字串的长度 !!!!!!!!!!!!$substring是正则表达式.!!!!!!!!! ...
随机推荐
- ES6函数参数默认值作用域的模拟原理实现与个人的一些推测
一.函数参数默认值中模糊的独立作用域 我在ES6入门学习函数拓展这一篇博客中有记录,当函数的参数使用默认值时,参数会在初始化过程中产生一个独立的作用域,初始化完成作用域会消失:如果不使用参数默认值,不 ...
- C 语言实例 - 字符转 ASCII 码
C 语言实例 - 字符转 ASCII 码 C 语言实例 C 语言实例 ASCII 定义了 个字符. 分类: 一:-.(删除键)是控制字符 二:空白字符:空格(). 制表符. 垂直制表符. 换行. 回车 ...
- tinymce 富文本简单使用
tinymce.init({ //选择器 selector:'textarea', //配置顶部的菜单栏显示隐藏 menubar: false, //配置中文(默认没有中文包,需要到官网下载,放到la ...
- OSPF-1-OSPF的数据库交换(2)
2.Hello过程: (1)在同一子网中发现其他运行OSPF的路由器 所有启用了OSPF的接口,都会监听发往224.0.0.5的组播Hello消息,这是表示所有OSPF路由器的组播地址.Hello包使 ...
- python 基础(四) 函数
函数 一.什么是函数? 函数是可以实现一些特定功能的 小方法 或者是小程序 优点: 提高 了代码的后期维护 增加了代码的重复使用率 减少了代码量 提高了代码可读性 二.函数的定义 使用 def关键+函 ...
- D.出题人的手环
链接:https://ac.nowcoder.com/acm/contest/358/D 题意: 出题人的妹子送了出题人一个手环,这个手环上有 n 个珠子,每个珠子上有一个数. 有一天,出题人和妹子分 ...
- javascript要点(上)
立即执行函数 即Immediately Invoked Function Expression (IIFE),正如它的名字,就是创建函数的同时立即执行.它没有绑定任何事件,也无需等待任何异步操作: ( ...
- (AOP)理解
AOP的全称: Aspact Oriented Programming AOP的目标(作用):让我们可以“专心做事” 日志记录,事务处理,异常捕获,缓存操作. AOP原理 将复杂的需求分解出不同 ...
- LINQ查询返回DataTable类型[轉]與将DataTable序列化为Json格式【轉】
(原文地址:http://xuzhihong1987.blog.163.com/blog/static/26731587201101853740294/) LINQ查询返回DataTable类型 在使 ...
- MySQL主从复制原理介绍
1)在mysql主库上,将改变记录到二进制日志(binary log)中. 2)在mysql从库上,IO线程将mysql主库上二进制日志(binary log)复制到中继日志(replay log)中 ...