【Shell基础】Bash基础与Linux三剑客

发布时间 2024-01-13 20:55:01作者: 三叔测试笔记

shell是什么?可以做哪些?

Shell是⼀种解释性的语⾔,适⽤于基本的逻辑处理和不追求速度的应⽤。

用于:

  • 人机交互
  • 批处理
    • Unix、Linux、Mac、Android、IOS
    • 脚本自动化
  • 工作场景
    • 服务端测试
    • 移动测试
    • 持续集成与自动化部署

shell种类

  • bash
  • sh
  • zsh
    windows没有/etc/shells,需要安装cygwingit bash

Bash基础

$符号含义

在bash里,$符号表示当前用户为普通用户;在bash脚本里, $开头表示变量。

  • $# 表示参数个数。
  • $0 是脚本本身的名字。
  • $1 是传递给该shell脚本的第一个参数。
  • $2 是传递给该shell脚本的第二个参数。
  • $@ 表示所有参数,并且所有参数都是独立的。
  • $$ 是脚本运行的当前进程ID号。
  • $? 是显示最后命令的退出状态,0表示没有错误,其他表示有错误。
  • ;号,可以将两段代码相连

变量定义

a=1  # 定义变量(=两边不能有空格)
a=1;b=2  # 定义多个变量
echo $a  # 引用变量,进行打印
echo ${a}_xxx  # {}引用变量----严谨写法
echo "字符串:$a"  # 双引号中才能引用变量

预定义变量

# 系统已经预制好的变量
echo $PWD
echo $USER
echo $HOME
echo $PATH

数组变量

array=(1 2 3 4 5)  #定义数组,中间空格相隔
echo ${a[@]}  # 打印数组所有数据(@或*),可以下标获取对应值
echo ${#a[*]}  # “#”打印长度

命令变量

a=`ls`  # 反引号(`)符号可以将命令结果进行变量设置
array=(`ls` `pwd`)  # `符号也适用于数组
echo $a

特殊符号的使用

变量类型

a="XX"  # 字符串
i=123  # 数字
a=true  # 布尔

数字型变量

# 计算
i=5
echo $((i+5))  
# 更新
((i=i+1))
echo $i
((i--));echo $i
((i++));echo $i
# shell是不支持浮点数,要想计算浮点数就要使用awk
awk 'BEGIN{print 1/3}'

比较变量

a=4;b=6
((a>b))
echo $?  # 显示最后命令的退出状态,0表示没有错误,其他表示有错误

字符串操作

s="hello word"
echo ${s:3}  # 字符串切片操作
echo ${#s}  # 字符串长度
# 掐头
echo "${s#hello}"  # 掐头,输出:word
echo "${s#*o}"  # 匹配从头到o的字符串,进行掐头
echo "${s##*m}"  # 贪婪匹配,一直匹配到最后一个
# 取尾
echo "${s%word}"  # 取尾,输出:hello
echo "${s%w*}"  # 匹配从尾往前到w的字符串,进行取尾
echo "${s%%o*}"  # 贪婪匹配,取尾
# 替换字符串
echo ${s/hello/hi}  # 第一个/符号后填待替换内容,第二个填需要替换的内容}

布尔变量

  • true
  • false
  • 命令执行返回 $?
    • 任何命令执行都会有一个返回值
    • 0表示正确
    • 非0表示错误
ls
echo $?  # 执行ls后,最后命令状态为0
ls xxx(不存在文件)
echo $?  # 不存在文件,最后命令状态为2
false
echo $? # false后,最后仅拿过来状态为1

判断类型

  • 算术判断
  • 字符串判断
  • 逻辑判断
  • shell内置判断

算术判断

[ 2 -eq 2 ]  # 相等
[ 2 -ne 2 ]  # 不等
[ 3 -gt 1 ]  # 大于
[ 3 -ge 1 ]  # 大于等于
[ 3 -lt 1 ]  # 小于
[ 3 -le 1 ]  # 小于等于

(())也可以表示算术比较。如:((10>=8)),((11==1))

逻辑判断

[ 2 -eq 2 -a 3 -ge 4 ]  # -a等同于&&(and并且)---与
[ 2 -eq 2 -o 3 -ge 4 ]  # -o等同于or---或

[[ 2 -eq 2 && 3 -ge 4 ]]  # 与
[[ 2 -eq 2 || 3 -ge 4 ]]  # 或

[ ! 2 -ge 1 ];echo $?  # 非

内置判断

使用实例:
[ -e code ];echo $? 

逻辑控制

  • 条件 if
  • 分支 case
  • 循环 for while until select
  • && ||
  • Break 和 continue

if结构

if[condition];then ...;fi
if[condition];then ...;else ...;fi
if[condition];then ...;elif ...;fi

简单的逻辑可以使用 && || 去替代

[ -e test]&&echo true||echo false  # [ -e test]执行成功才会打印ture,若执行不成功则打印false

条件可以用命令返回值代替

分支 case

For循环

for((i=0;i<10;i++));
do
echo $i
done

另外一种写法:

for i in ${array[@]};do echo $i;done\
for i in `ls`;do echo $i;done

While循环

i=0;while [ $i -lt 3 ];do echo $i;((i=i+1));done

>符号输出重定向;<符号输入重定向

# 一行一行读取文件内容---"<"符号输出给read方法读取
while read line; do echo $line;done < /tmp/tmp
# >输入重定向
echo "文件内容写入xxx" > a.txt
# >>追加重定向
echo "文件内容写入xxx" >> a.txt

until

退出控制

  • return 函数返回
  • exit 脚本返回
  • break 退出当前循环。默认1
  • break 2 退出两层循环
  • continue 跳过当前的循环,进入下一次循环
  • continue 2 跳到上层循环的下一次循环中

break

# 判断当前路径文件和目录,文件则跳出不打印
for i in *;do echo $i;if [ -d $i ];then break;fi;done

continue

# 判断当前路径文件和目录,文件则调到下一次循环中
for i in *;do echo "检查:${i}";if [ -f $i ];then echo $i is file;else echo $i not is file continue;fi;done

Shell运行环境概念

  • bash是一个进程
    • bash下还可以再重新启动一个shell,这个shell是sub shell,原shell会复制自身给他
    • 在sub shell中定义变量,会随着sub shell的消亡而消失
()  子shell中运行
  a=2;(a=1;echo $a);echo $a
{}  当前shell中运行
  a=1;{ a=12;echo $a;};echo $a
$$ 当前脚本执行的pid
&  后台执行
  sleep 3&
$! 运行在后台的最后一个作业的PID(进程ID)
  echo $!
ps 查看进程
jobs 查看任务
bg  继续任务
  bg 1
fg 暂停任务
  fg 1

文件添加权限

chmod +x test.sh
# 设置环境变量
./bash_profile
source ~/.bash_profile

Linux三剑客(grep、awk、sed)

  • grep 查找功能
  • awk 取列
  • sed 取行和替换

grep(搜索匹配)

grep -i "ccc" < a.txt  # -i 忽略大小写
grep -o "c" < a.txt  # -o 只匹配填写的内容
grep -o "c." < a.txt  # .任意一个字符
grep -o "c.*" < a.txt  # .任意多个字符
cat a.txt  | grep "aaa"  # |管道符传递数据给grep

正则匹配

多功能联合使用

# 从文档中获取数据,然后循环读取出变量,进行请求,并进行搜索匹配出对应字段值
while read line;do echo $line;curl -s http://www.baidu.com/s?wd=$line;done <baidu.keyword | grep -o "timestamp=[0-9]*"

awk(强大的文本分析工具)

#  使用+、_进行分割字符(-F,指定分隔符)
echo "123_456+789" | awk -F '+|_' '{print $1}'  # 结果为:123
# 不指定-F,默认空格进行分割的
ls -al | awk  '{print $1,$3}'




sed(替换)

# 将aaa替换成AAA
echo "aaa bbb ccc ddd" | sed 's/aaa/AAA/'  # 输出:AAA bbb ccc ddd
# 出现多个时,末尾加g,替换所有
echo "aaa bbb ccc ddd aaa" | sed 's/aaa/AAA/g'  # 输出:AAA bbb ccc ddd AAA
# 也可以使用其他符号进行分隔,如:(|、+、#符号等)
echo "aaa bbb ccc ddd aaa" | sed 's#aaa#AAA#g'
# 替换文本(!!!会替换到模式空间的内容,不会修改源文件)
sed 's/aaa/AAA/' a.txt
sed -i 's/aaa/AAA/' a.txt # -i替换源文件
sed -i.bak 's/aaa/AAA/' a.txt  # 重要!!!生成备份文件(bak可以随意命名)(文件名:a.txt.bak)

函数

[function]name(){
...
}

function可以省略。---可以在脚本文件定义,也可以再shell中定义
如果没有return,返回值是最后一句的指令的返回值。

函数应用示例

# 脚本文件test1.sh中定义函数
functest(){
	echo "获取脚本执行参数: $0";
	echo "获取第一个参数: $1";
	echo "获取第二个参数: $2";
	echo "获取参数的个数: $#";
	echo "获取到的参数(str): $*";
	echo "获取到的参数(每一个参数都是一个str): $@";
	echo "获取当前进程的ID号(PID): $$";
}
functest a b c d

# shell中执行脚本文件
./test1.sh

执行结果:

练习

打印竖行2/5/8之和

echo -e "1|2|3\n4|5|6\n7|8|9"

echo -e "1|2|3\n4|5|6\n7|8|9" | awk -F '|' 'BEGIN{a=0}{a=a+$2;print $2}END{print a}'  # 输出和为15

可以输入任意参数,直到输入quit才会退出程序

# input.sh脚本文件
while true
do
read -p "please enter:" var_q
  if [ $var_q == "quit" ]
    then
      break
   else
      echo ${var_q}
  fi
done

运行结果: