bash 执行命令 不改变环境
./ 执行命令 改变环境
变量
定义变量:
变量名=变量值
1.等号两边不能有空格
2.变量值有空格的话需要有引号
变量名=`命令`
Czombie=`top -b -n 1 | grep Tasks | awk '{print $10}'`
反引号容易导致输出溢出的错误 所以最好拿变量接着
交互式定义变量:
read 变量名
read -p "请输入值" aa
调用变量
echo $变量
重复定义变量:
aa=12
aa="aa"456 -> aa=12456
*双引号特殊字符依旧有用 单引号特殊字符只是字符 *
位置变量:
$n : n为数字,$0代表脚本本身,1~$9代表1~9参数,10以上的参数需要用大括号包含,如:${10}
$@:命令行所有参数,但每个参数区别对待
$*:命令行所有参数,所有参数视为一个整体
$#:参数总个数
$$:脚本运行的当前进程ID号
预定义变量
$0 代表脚本本身
$* 显示所有参数内容
$# 显示有多少个参数 *这里指的是未知参数*
$$ 显示脚本进程号PID
$? 显示上一条命令的执行结果(0代表正确,非0代表错误
*注意 "字符串 $1" 是可以触发特殊字符的作用的*
整数运算
$(())
语法(* -> 乘法):
$((num1 + num2))
let
语法:
let i++
小数运算
原理:awk可以对参数进行格式化 与 正则
echo “$2 $3” | awk ‘{ printf “%.2f”, $1 + $2}’
变量=$(echo “$2 $3” | awk ‘{ printf “%.2f”, $1 + $2}’)
实例
echo "123456" | passwd --stdin &name &> /dev/null
--stdin 标准输入,不在询问
条件测试
数值比较
语法:[ 整数1 操作符 整数2 ]
int1 -eq int2 两数相等为真
int1 -ne int2 两数不等为真
int1 -gt int2 int1大于int2为真
int1 -ge int2 int1大于等于int2为真
int1 -lt int2 int1小于int2为真
int1 -le int2 int1小于等于int2为真
小数判断:
if [ $(echo "$2 != 0 " | bc) = 1 ];then
有效数字的判断:
if [[ $arg =~ ^[0-9]*(\.[0-9]*)?$ ]]
[]也是字符 所以不能与其他字符直接相连
文件测试
语法:[ 操作符 文件或目录]
-f filename 存在返回真
-b filename 存在且是块文件返回真
-d filename 存在且是目录返回真
-h filename 存在且是符号链接返回真
-c filename 存在且是字符文件返回真
-e filename 存在且是文件或目录则返回真
-r filename 存在且是目录或文件且可读为真
-w filename 存在且是目录或文件且可写为真(相对用户而言 例如root 所有文件都可写 哪怕无写权限)
-s filename 存在且文件且大小大于0为真
字符串比较
语法:[ “字符串” = “字符串” ]
=,!=,-z(判断字符长度是为0),-n(判断字符长度不是为0)
if [ -z $a ]
多条件测试:
and(&&),or(||)
if [ "$score" -ge "0" ]&&[ "$score" -lt "60" ];then
流程控制If
单分支:
if command/[test] ; then
command
fi
根据上条命令判断用户是否存在
id &name &> /dev/null
if [ $? -ne 0]
判断用户是否输入
if [ $# -ep 0]
双分支:
if command/[test] ; then
command
else
command2
fi
多分支:
if 条件测试 ; then
command1
elif 条件测试 ;then
command2
else
command3
fi
嵌套分支:
if 条件测试1 ;then
command
if 条件测试1 ;then
command2
fi
fi
调试脚本
sh -n 脚本 语法检测
sh -xv 脚本 动态调试
常见错误:
1.if then同一行必须加;
2.if判断中变量一般加双引号,以免误会、
3.-z,-n检查长度,没有定义的变量也为0
4.空变量与没有初始话的变量会产生严重错误 所以一定要通过判断剔除掉未输入情况
模式匹配case
语法:
case 变量 in
模式1)
命令序列1
;;
*)
无匹配后命令序列
;;
esac
case "$action" in
y|Y|yes|Yes)
*EOF EOF表示中间是一段话 cat <<EOF EOF 读取话并传到屏幕
-EOF EOF不保留缩进
*
循环:for
语法:
for 变量名 [ in 取值列表 ]
do
循环体
done
for ((i = 1; i <= fip; i++));
for i in {1..10}
for i in $(seq 1 10)
for i in `cat useradd.txt` #反引号
>ip.txt 清空文本
| tee 三向管道 传到屏幕与文件 | tee -a ip.txt
{ 循环体 } &:高并发 但无顺序
wait 等待前一个程序执行完毕 执行下一个命令
循环for
while 条件测试 #逐行处理文件
do
循环体
done
expect
#!/bin/expect
spawn ssh root@hostname #这个程序需要交互
expect {
#exp_continue 当"yes/no"不存在时跳过
"yes/no" { send "yes/r";exp_continue }
"password" { send "6666/r" }
}
interact #停留在spawn后的界面
bash内部调用expect
/bin/expect<< -EOF
set timeout 10
spawn ssh-copy-id $ip
expect {
"yes/no" { }
}
##执行完spawn回到原环境
expect eof
EOF
数组
定义:
hero={ 1 2 3 4}
hero={`cat /etc/passwd`}(这个貌似不对)
groupList=`groups shenchen | cut -d : -f 2 `
hero={$red $blue $green}
关联数组
declare -A hero
hero={ [up]=1 [center]=2}
访问:
echo ${array2[0]}
echo $(array2[*]) 访问所有元素
echo $(array2[*]:1:2) 访问截断元素
echo ${!array2[*]} 查看所有索引->关联性
变量的索引与步长->截断
name=meinanzi
${name:3:3} -> nan
数组和while循环(读取文件) 使用换行符隔开:
读取文件每行
while read line
do
hosts[i++]=$line
done< /etc/hosts
echo "$(host[$i])"
数组和for循环(读取文件) 使用空格隔开:
# 分隔符改变后 使用换行符隔开
#IFS=$'\n' 基本不用
#数组本来就是动态的
for aaa in 'cat /etc/hosts' (${groupList})
do
hosts[i++]=$line
done
类型统计
type=`echo $line | awk '{ print $2 }'`
let shells[&type]++
函数
定义函数
函数名() {
函数要实现的功能代码
}
调用函数
函数名
正则表达式
用于在查找过程中匹配指定的字符
基本正则表达式
^ 行首定位符 (行开头)
grep ^root /etc/passwd
$ 行尾定位符
grep love$ 1.txt
. 匹配任意单个字符
grep a.c 1.txt
abc adc afc
* 匹配前导符出现0次到多次
grep "abc*" 1.txt
ab abcd abcde
*ls 1* 任意长度任意字符 这是shell环境下
.* 任意多个字符
[] 匹配制定范围内的一个字符
grep "[lL]ove" 1.txt
[-] 匹配连续字符
grep "[0-9]ove" 1.txt
[^] 匹配不在指定组内的字符
grep love[^a-zA-Z0-9] 1.txt
\ " " ' ' 转义字符
grep "l\.ve" 1.txt
l.ve
\< 词首定位符 (单词开头)
grep "\<love" 1.txt
love123
/> 词尾定义符
grep "love\>" 1.txt
love123
() 将组合信息
x\{m\} 字符x重复出现m次
x\{m,\} 字符x重复出现m次以上
扩展正则表达式元字符
+ 前导符1~n次
?前导符0~1次
a|b 匹配a|b
()
egrep "love(able|rs)" 1.txt
loveable lovers
lovers
/^$/ 空行
退出当前程序 exit 1
grep
过滤文档的内容
egrep 支持扩展正则
fgrep 不支持正则
-q 不返回结果到屏幕
-R 查找目录下面的所有文件
grep -R love /home
Cut
cut 命令从文件的每一行剪切字节、字符和字段并将这些字节、字符和字段写至标准输出。
参考文档:
【Shell】shell截取字符串方式(cut、awk、sed命令) - 陈晓猛 - 博客园 (cnblogs.com)
shell可以自动执行的位置补充
(笔记)在每个 Linux 用户SSH登录时执行自定义脚本 - tdyizhen1314 - 博客园 (cnblogs.com)