Shell 编程日记

2023-06-15 14:45:04 浏览数 (1)

Shell 脚本语法

  • Shell 解释器

名称

路径

简介

Bourne Shell

/usr/bin/sh或/bin/sh

Bourne shell是AT&T开发的原始UNIX shell以其开发人员Stephen Bourne命名,Bourne shell也以其程序名sh闻名

Bourne Again Shell

/usr/bin/bash

bash是大多数Linux系统以及Mac OS X默认的shellBash 可以说是bourne shell增强版

C Shell

/usr/bin/csh

C Shell Bill Joy于20世纪80年代早期,在Berkeley的加利福尼亚大学开发了C shell;主要是为了让用户更容易的使用交互式功能,并把ALGOL风格的语法结构变成了C语言风格

Korm Shell

/usr/bin/ksh

贝尔实验室的David Korn在上世纪80年代初开发基于Bourne shell的源代码发展而来,向后兼容的Bourne Shell,包括C shell的诸多特性

....

  • Shell 脚本执行顺序依旧遵循“从上往下、从左往右”的顺序;
  • Shell 脚本就是把一些命和运算符写进脚本文件,然后完成批量重复性工作而已;
  • Shell 脚本支持流程控制,如 forwhileif 等语句控制;
  • Shell 脚本句末无须标点符号标记,换行即表示语句结束;
  • Shell 脚本严格区分大小写,a 和 A 是完全不同的两个字符串;
  • Shell 脚本通常的以 /usr/bin/bash 开头,必须以此句开头,表示 shell 脚本解释器;
  • Shell 脚本注释用 # 开头,但第一句除外/usr/bin/bash
  • Shell 脚本通常以 .sh 为后缀命名,约定成俗;
  • Shell 脚本调试可以使用 bash -x xx.sh 运行脚本,系统会打印出每一条语句及执行结果;

Shell 基础语句

语样

描述

例子

001

echo "string"

打印(输出/显示)内容

打印 Hellow Shell 到屏幕echo "Hellow Shell."

002

>

重定向输出(不追加,会覆盖前面已有的内容)

把 Hellow Shell 输出到 test.txt 文档echo "Hellow Shell." > test.txt

003

>>

追加重定向输出(末行追加,不覆盖前面已有的内容)

把 Hellow Shell 输出到 test.txt 文档echo "Hellow Linux." >> test.txt

004

<

重定向输入

005

``

命令替换,先运行``里面的命令,然后把结果赋给变量

把时间赋值给DATE 变量DATE=`date %T`

006

$()

命令替换,等同于``,但推荐使用$()

把时间赋值给DATE 变量DATE=$(date %T)

007

${}

变量引用,推荐

声明变量 T 并打印输出到屏幕T=$(ls -l)echo ${T}

008

|

管道符,把前一个命令执行的结果作为后一个命令的输入

查看文件 test.txt 并统计行数cat test.txt | wc -l

009

(())

双括号一般用于计算val :后增val-- : 后减 val : 先增--val : 先减! : 逻辑求反~ : 位求反** : 幂运算<< : 左位移>> : 右位移& : 位布尔和| : 位布尔或&& : 逻辑和|| : 逻辑或

计算5 3(( 5 3 ))

010

[[]]

支持模式匹配,支持正则表达式(不是所有的shell都支持[[]])

...


Linux 退出状态码

状态码

描述

0

命令成功结束

1

一般性未知错误

2

不适合的shel命令错误

126

命令不可执行

127

没有找到相关命令

128

无效的退出参数

128 x

与Linux信号x相关的严重错误

130

通过Ctrl C终止

255

正常范围之外的退出状态码


数组相关

  • 数组定义

定义数组建议“见名知意”,元素之间用空格分隔,数组元素下标从 0 开始

代码语言:javascript复制
arry_name=(value1 value2 value3 ...)     // 格式1,适用于元素较少情况

arry_name=(
  value1
  value2
  value3
  ...
)     // 格式2,适用于元素较多情况
  • 数组元素操作

需要注意数组的作用域,博主就遇到数组作用域问题

代码语言:javascript复制
arry_sname=(zhangsan lisi wangwu zhaoliu)  // 定义数组 arry_sname
echo ${arry_sname[0]}                      // 打印第一个元素
echo ${arry_sname[*]}                      // 打印所有元素
echo ${arry_sname[@]}                      // 打印所有元素
echo ${#arry_sname[*]}                      // 打印数组长度
echo ${#arry_sname[@]}                      // 打印数组长度
  • 素组元素修改
代码语言:javascript复制
arry_sname[3]=value4                      // 添加新的元素,如果下标元素存在,则值会被替换
unset arry_sname[3]                       // 删除下标为3的数组元素
unset arry_snme                           // 删除数组

Shell 测试语句

在Shell 脚本中,表达式要 [] 括起来,且表达式两边均要有空格

  • 数值比较

比较表达式

描述

n1 -eq n2

n1 = n2

n1 -ge n2

n1 >= n2

n1 -gt n2

n1 > n2

n1 -le n2

n1 <= n2

n1 -lt n2

n1 < n2

n1 -ne n2

n1 ≠ n2

  • 字符串比较

比较表达式

描述

str1 = str2

str1 = str2

str1 != str2

str1 ≠ str2

str1 < str2

str1 < str2

str1 > str2

str1 > str2

-z str1

str1 长度非0

-n str1

str1 长度为0

  • 文件比较

比较表达式

描述

-d file

file 是否存在且是一个目录

-e file

file 是否存在(目录或文件)

-f file

file 是否存在且是一个文件

-r file

file 是否存在且可读

-s file

file 是否存在且非空

-w file

file 是否存在且可写

-x file

file 是否存在且可执行

-o file

file 是否存在且所有者属于当前用户

-G file

file 是否存在且默认组与当前用户组相同

file1 -nt file2

file1 是否比 file2 新

file1 -ot file2

file1 是否比 file2 旧


Shell 流程控制语句

  • IF 语句
代码语言:javascript复制
// 单条件
if 条件;then
   命令1
   命令2
   ....
fi

---------------------------

// 双条件

if 条件;then
   命令1
   命令2
   ....
else
   命令3
   命令4
   ....
fi

---------------------------
// 多条件

if 条件1;then
   命令

elif 条件2;then
   命令

elif 条件3;then
   命令

else
   命令
fi
  • While 语句
代码语言:javascript复制
// while 从某种意义上来讲,可以说是 if-then 语句和 for 循环的混杂体
// while 语句中,只有当测试条件为 true 时,才会不断循环下去,直至遇到 false
while 测试条件
do
    命令
done
  • For 语句
代码语言:javascript复制
// for 语句是按行逐一遍历数据,以回车换行为分割
// list 支持命令,支持变量引用
// for 循环默认会以空格换行,所有如果你的行有空格的话
// 在 for 循环前,设置换行符(其它符号类似) IFS.old=$IFS;IFS=$'n'
// 同时在 for 循环完成后,记得还原 IFS=$IFS.old
for var in list
do 
    命令
done


// Bash for 语句支持C语言风格,注意空格
for (( i=1;i<10;i   ))
do
   命令
done

// for 支持多变量,注意空格
for (( i=1,j=10;i<10;i  ,j-- ))
do
   命令
done
  • case 语句
代码语言:javascript复制
case 变量 in
    值a)
       代码 A
      ;;
    值b)
       代码 B
      ;;
    值c)
       代码 C
      ;;
    *)
       代码 D
      ;;
esac

Shell 函数创建与调用

  • 函数创建(function)
代码语言:javascript复制
// 语法格式,其中 function可以省略,但是建议标准化格式
function name {
    命令
    内容
}
  • 函数调用
代码语言:javascript复制
// 调用函数,直接写函数名即可
test

sed、awk 用法

  • sed 编辑器(流编辑器)
代码语言:javascript复制
// sed 常见用法
// 常规替换字符,默认情况只替换第一次匹配到的字符串
sed 's/str_old/str_new' file

// 按要求替换(flag)
sed 's/str_old/str_new/3' file  // 匹配到的第三处替换,3 是需要替换的第几次匹配到的意思
sed 's/str_old/str_new/g' file  // 匹配到全文替换
sed '2s/str_old/str_new' file  // 按行匹配替换:匹配第二行内容,并替换
sed '2,3s/str_old/str_new' file  // 从第二行开始匹配,到第三行结束,并替换
sed '2,$s/str_old/str_new' file  // 从第二行开始全文匹配,并替换

// 删除行操作
sed '5d' file  // 删除文件 file 第 5 行内容
sed '2,7d' file // 删除文件 file 第 2~7 行内容
sed '7,$d' file // 删除文件 file 第 7 行以后所有的行

// 插入操作,如果使用变量,请使用双引号
sed -i "Line i str" file  // 在 Line行前插入 str(新行),i 前可以加数字(3i)表示第几行前插入
sed -i 'Line a str" file  // 在 Line行后插入 str(新行),a 前可以加数字(3a)表示第几行后插入

// 追加操作

Shell 小技巧/样例

  • 跳出循环语句
代码语言:javascript复制
// 跳出当前循环
break

// 跳出指定循环,n 是循环层级
break n
  • 关键字匹配(涉及正则表达式)
代码语言:javascript复制
// 匹配关键字信息,str1 字符串包含 str2 内容
[[ str1 =~ str2 ]]
  • 字符串替换
代码语言:javascript复制
// 字符串替换,如果末尾加 /g 表示全部替换
var1='abc123'
var=${var1/'bc1'/'BC1'}
  • EOF 格式化输出
代码语言:javascript复制
// 格式输出到指定文件,EOF 只是标记,不是关键字
cat >> test.txt <<EOF
    内容
    命令
EOF
  • 提示并接收用户输入数据
代码语言:javascript复制
// read 可以接收用户输入的内容,把用户敲入的用户赋值给 username
read -p "请输入用户名:" username

// 设置等待输入超时
read -t 5 -p "请输入用户名:" username


// 隐藏模式输入,如 Linux 输入密码一样
read -s -p "请输入密码:" userpasswd
  • Shell 多进程示例
  • 正则表达式
代码语言:javascript复制
待更新...

0 人点赞