首页 > 系统相关 >Shell脚本编程基础

Shell脚本编程基础

时间:2024-11-26 10:48:47浏览次数:4  
标签:脚本 shell 变量 编程 echo 命令 Shell file

一、构建基本脚本

1.1 使用多个命令

  1. 两个命令一起运行,放在同一行,用;隔开,例如pwd; ls

1.2 创建shell脚本

  1. 在创建shell脚本文件时,必须在文件的第一行指定要使用的shell。其格式为:#!/bin/bash
    • 井号(#)用作注释行。shell并不会处理shell脚本中的注释行。然而,shell脚本文件的第一行是个例外,#后面的惊叹号会告诉shell用哪个shell来运行脚本。

1.3 显示消息

  1. 使用echo 内容

    • -n不换行
    • -e启用转义字符,echo默认不处理转义字符
  2. 防止字符串被Shell特殊字符解析

    • 输出内容用""双引号包裹:允许变量和转义字符的解析
    • 输出内容用''单引号包裹:完全禁止解析,包括变量
  3. 长文本输出,使用\反斜杠

    echo "This is a \
    long line"
    
  4. 命令捕获:将命令传给echo,使用$(命令)

    • echo "current pwd is $(pwd)"
      

1.4 使用变量

  1. 环境变量可以直接用使用,用$环境变量即可。
  2. 用户变量可以是任何由字母、数字或下划线组成的文本字符串,长度不超过20个。用户变量区分大小写。
  3. 在变量、等号和值之间不能出现空格
  4. shell脚本会自动决定变量值的数据类型。
  5. 引用一个变量值时需要使用美元符,而引用变量来对其进行赋值时则不要使用美元符
  6. 为了避免变量与其他内容混淆,可以使用{}包裹变量,例如echo "your name is ${name}"

1.5 重定向输入和输出

  1. 输出重定向

    • 命令 > 文件,将命令内容保存到指定文件,这个会覆盖原文件
    • 命令 >> 文件,这个不会覆盖原文件,是追加操作。
  2. 输入重定向

    • 命令 < 文件,将文件的内容重定向到命令。

    • 内联输入重定向命令 << 结束标记,可以不使用文件进行重定向,在命令行中指定输入重定向的数据。

      [tom@Centos7 bash_learn]$ wc << EOF
      > hello 
      > ouyang
      > 18
      > EOF
       3  3 17
      

1.6 管道

  1. 将一个命令的输出作为另一个命令的输入,就可以使用管道。命令一 | 命令二
  2. Linux系统实际上会同时运行这两个命令,在系统内部将它们连接起来。在第一个命令产生输出的同时,输出会被立即送给第二个命令。数据传输不会用到任何中间文件或缓冲区

1.7 数学计算

  1. 使用$[运算],只能整数运算
  2. bc计算器
    • 输入bc后,就可以进入计算器页面,可以定义变量,进行计算
    • 在脚本中使用:var1=$(echo "scale=4; 3.44 / 5" | bc)

1.8 退出脚本

  1. shell中运行的每个命令都使用退出状态码(exit status)告诉shell它已经运行完毕。退出状态码是一个0~255的整数值,在命令结束运行时由命令传给shell。可以捕获这个值并在脚本中使用。
  2. $?表示上一个命令的执行结果,0通常代表成功。
  3. 默认情况下,shell脚本会以脚本中的最后一个命令的退出状态码退出。
  4. exit命令允许你在脚本结束时指定一个退出状态码。
    • 直接终止整个shell脚本

1.9 运行脚本的不同方式

  1. 使用路径(绝对路径或相对路径)执行./test.sh
    • 脚本运行在一个新的子shell中,环境是独立的。也就是说,脚本中的变量、函数、工作目录的改变等,只在子 Shell 中生效,不会影响当前 Shell。
  2. 指定shell运行bash test.sh
    • 脚本运行在一个新的子shell中,环境是独立的
  3. 使用source test.sh或者. test.sh
    • 在本shell中执行,环境不是独立的

二、结构化命令

2.1 if-then 语句

  1. 基本语法

    if 命令   # 如果命令的退出状态码是0,则表示成功,就会执行then后面的部分,否则不执行
    then 
    	命令
    fi
    
    • 另一种形式
      if 命令; then
      命令
      fi   
      # 这种形式更像其他编程语言的if
      

2.2 if-then-else 语句

  1. 基本语法
    if 命令; then
    命令
    else 
    命令
    fi
    

2.3 if-then-elif-then-else 语句

  1. 基本语法
    if 命令; then
    命令
    elif 命令; then
    命令
    else 
    命令
    fi
    

2.4 test语句

  1. 上述的if后面,紧跟着必须是命令,并且通过命令的状态码,来决定是否执行then语句。
  2. test命令中列出的条件成立,则会返回0,这样一来,就和其他语言的if-else类似了。
  3. 基本语法:test 条件,如果没有条件,则直接返回0
    • 还有另一种方式if [ 条件 ],注意,第一个方括号后和第二个方括号前必须有一个空格
  4. 数值比较
    • 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
    • 只能使用整数
  5. 字符串比较
    • str1 = str2 检查str1是否和str2相同
    • str1 != str2 检查str1是否和str2不同
    • str1 < str2 检查str1是否比str2小
    • str1 > str2 检查str1是否比str2大
    • -n str1 检查str1的长度是否非0
    • -z str1 检查str1的长度是否为0
  6. 文件比较
    • -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旧
  7. 复合条件测试
    • 并且 [ condition1 ] && [ condition2 ]
      • 短路与,如果前者为假,后者不会执行
    • [ condition1 ] || [ condition2 ]
      • 短路或,如果前者为真,后者不会执行

2.5 if-then的高级特性

  1. 双括号:使用高级数学表达式
    • val++ 后增
    • val-- 后减
    • ++val 先增
    • --val 先减
    • ! 逻辑求反
    • ~ 位求反
    • ** 幂运算
    • << 左位移
    • >>右位移
    • &按位与
    • |按位或
    • &&逻辑与
    • ||逻辑或
  2. 双方括号:字符串比较的高级特性。
    • 提供了模式匹配

2.6 case命令

  1. 基本语法

    • case 变量 in
      模式1 | 模式2) 
      命令;;
      模式三)
      命令;;
      *)    # 都没匹配上时
      命令
      esac
      

2.7 for命令

  1. 基本语法

    for var in list
    do
    命令
    done
    
    • for命令遍历list,每次都会赋给var,list中的分隔符,默认是空格
  2. 更改字段分隔符

    • 有一个特殊的环境变量IFS,内部字段分隔符,定义了shell用作分隔符的一系列字符。
    • 改成换行符IFS='$\n'
    • 如果要指定多个IFS字符,只要将它们在赋值行串起来就行。IFS=$'\n':;"
      • 使用换行符,冒号和分号
  3. 使用通配符读取目录

    • for file in /home/rich/test/*    # 读取所有文件(夹)
      do
      if [ -d "$file" ]    # 为啥需要用双引号包裹,因为文件名可能有空格
      then
      echo "$file is a directory"
      elif [ -f "$file" ]
      then
      echo "$file is a file"
      fi
      done
      
  4. C语言风格的for

    • # 感觉很奇怪。。。
      for (( i=1; i <= 10; i++ ))
      do
      echo "The next number is $i"
      done
      $ ./test8
      The next number is 1
      The next number is 2
      The next number is 3
      The next number is 4
      The next number is 5
      The next number is 6
      The next number is 7
      The next number is 8
      The next number is 9
      The next number is 10
      

2.8 while命令

  1. 基本语法

    while 测试命令
    do
    命令
    done
    
  2. 多个测试命令

    while 测试命令一
    测试命令二
    do
    命令
    done
    
    • 多个测试命令都会执行,注意,只以最后一个的执行结果来判断是否进入do

2.9 until命令

  1. 基本语法

    until 测试命令
    do
    命令
    done
    
  2. 和while相反,只有返回不为0,才会执行

  3. 同样也可以有多个测试命令,只看最后一个的执行结果。

2.10 break命令

  1. 作用:跳出单个循环
  2. 跳出外部循环break n,指定跳出的循环层级,默认不加就是1.

2.11 continue命令

  1. 作用:中止某次循环。
  2. 和break类似,可以使用continue n,指定中止的循环层级

2.12 处理循环的输出

  1. 可以将循环的输出结果重定向到文件中
    for file in /home/rich/*
    do
    if [ -d "$file" ]
    then
    echo "$file is a directory"
    elif
    echo "$file is a file"
    fi
    done > output.txt    # 在这里重定向 
    

2.13 使用循环的例子

  1. 查找可执行文件

    • 如何模拟shell,查找PATH中的可执行文件?

    • 首先,PATH中定义了许多可执行文件的路径,使用进行分割,所以我们要修改IFS=:

    • 然后就可以遍历PATH中的所有路径,然后要保证是文件,并且具有执行权限。

    • IFS=:
      for folder in $PATH
      do
      	echo "$folder:"
      	for file in $folder/*
      	do
      		if [ -f "$file" ] && [ -x "$file" ]
      		then
      		echo " $file"
      		fi
      	done
      done
      
  2. 批量创建用户

    • 现在需要批量创建用户,有一个文件users.csv,里面的内容是id,名字 姓,也就是说两个字段,一个id,一个name,那么是包含空格的。

    • input="users.csv"
      # 从文件中读取,分隔符改成,
      while IFS=',' read -r userid name
      do
      	echo "adding $userid"
      	useradd -c "$name" -m $userid
      done < "$input"
      

三、处理用户输入

3.1 命令行参数

  1. 执行脚本时./test.sh 10 30,其中的1030就是传入的参数
  2. $0是程序名,$1是第一个参数,$2是第二个参数,以此类推,$9是第九个。第十个之后的参数${10}
  3. 获取脚本名,可以使用函数basename,例如,name=$(basename $0)

3.2 特殊参数变量

  1. 统计命令行中输入了多少个参数$#,程序名$0不被计算在内。
  2. $*会将命令行上的所有参数当作一个单词保存,不包括$0
    • 可以使用for循环分割,但是如果某个参数就包含空格时,就会出问题。
  3. $@保存命令行的所有参数,同时保留参数边界。
    • 如果有空格,可以for var in "$@",用双引号包裹即可。

3.3 移动变量

  1. 使用shift命令,每执行一次,可以将所有参数往左移一个,也就是说$2变成$1$3变成$2,注意,不会改变$0,也就是说$1被移没了。
  2. shift n,移动n个
  3. 有啥用?可以依次处理参数,处理完一个后,就可以移出了。

3.4 处理命令行选项和参数getopt

  1. 命令格式getopt optstring parameters

    • 在optstring中列出脚本中用到的每个命令行选项字母,然后如果某个选项需要参数,则加一个:
  2. 例子

    # 需要abcd选项,b选项需要一个参数
    $ getopt ab:cd -a -b test1 -cd test2 test3
    -a -b test1 -c -d -- test2 test3 # --是为了分隔开选项和参数 --后就是参数了
    $
    
  3. getopt是将空格当作分隔符,也就是说,如果某个参数有引号,即使用双引号包裹起来,也不起作用。

  4. 在脚本中使用set -- $(getopt -q ab:cd "$@")

    • -q是忽略错误
    • 将用户的参数,交给getopt,并且替换成$1$2等等。

3.5 获得用户输入

  1. 使用read 变量1 变量2,将用户输入到变量中。

    • 之后就会等待用户输入,按回车结束输入
    • 用户输入按空格分割分别赋值给变量1、变量2
    • 如果用户输入数目不够,则后面的变量,值为空
    • 如果用户输入的数目过多,最后一个变量,获取剩下的所有值
    • 也可以不指定变量,那么就会保存在REPLY环境变量中。
  2. -p输出提示信息

  3. -t seconds指定超时时间,如果超时都未输入,则会返回一个非0的状态码。

  4. -n5限制输入字符数

  5. -s使用户输入内容和shell背景色一样(输入密码时)。

  6. 通过文件读取

    • count=1
      # 通过管道  然后传给while循环,不断读取 每次读取一行
      cat test | while read line
      do
      	echo "Line $count: $line"
      	count=$[ $count + 1]
      done
      echo "Finished processing the file"
      

标签:脚本,shell,变量,编程,echo,命令,Shell,file
From: https://www.cnblogs.com/ouyangxx/p/18569631

相关文章

  • 《JAVA编程思想》第四版 PDF 下载 中文版和英文版 高清PDF扫描带书签
     转载自:https://www.cnblogs.com/buwuliao/p/8073211.html非常感谢也可见:https://www.cnblogs.com/ChaoJieLiu/p/12910447.html一、链接:中文版+英文版+思维导图:链接:https://pan.baidu.com/s/1bmgOdC7gFhI4Waac6JV4Wg提取码:s3vc复制这段内容后打开百度网盘手机App,操作更方......
  • JavaScript 编程精解(Eloquent)第四版·翻译完成
    JavaScript编程精解(Eloquent)第四版第一章:引言第一部分:语言第二章:值、类型和运算符第三章:程序结构第四章:函数第五章:数据结构:对象和数组第六章:高阶函数第七章:对象的秘密生活第八章:项目:一个机器人第九章:漏洞和错误第十章:正则表达式第十一章:模......
  • jmeter之录制脚本(badboy)
    脚本录制:一、badboy录制脚本1、设计性能场景2、根据性能场景录制性能脚本(badboy或者jmeter中反向代理录制脚本)=======================================3、badboy工具的使用(1)下载badboy包(2)安装badboy包第一步:第二步:找到安装路径:C:\ProgramFiles(x86)\Badboy创......
  • [编程笔记] 系统日期格式引起的bug
    系统获取的日期格式不对,导致程序出现异常,出现过多次了,这里记录一下。起因是测试说某个跟日期相关的活动,在他环境里失效,而我们开发本地测试了多遍都是正常的,这就很奇怪了,有种想给他重装系统的念头,哈哈。经过一系列的分析和排查,发现是他本地系统设置的日......
  • 幼儿编程启蒙、幼儿实物编程
    幼儿编程启蒙乐园第一集幼儿编程启蒙乐园第一集_哔哩哔哩_bilibili幼儿编程启蒙乐园幼儿编程启蒙乐园_哔哩哔哩_bilibili3-6岁线上实物编程3-6岁线上实物编程-网易云课堂3-6岁线上实物编程-学习视频教程-腾讯课堂适合低年龄孩子的儿童实物编程来了!适合低......
  • Go进阶21:Goland 6条Tips让编程更有效率
    作为一个重度使用JetbrainsIDE全家桶的用户.这里我有几条可以加速您开发速度,减少您Paste/Copy敲打键盘的Tips.1.快速实现Interface操作步骤:光标移动到struct名称上Alt/Option+Enter选择ImplementInterface…Control+I搜索您需要实现的interface2.快速抽象I......
  • shell编程(五):条件判断和循环结构
    声明:学习视频来自B站up主泷羽sec有兴趣的师傅可以关注一下,如涉及侵权马上删除文章。笔记只是方便各位师傅的学习和探讨,文章所提到的网站以及内容,只做学习交流,其他均与本人以及泷羽sec团队无关,切勿触碰法律底线,否则后果自负!一、IF条件判断和循环结构1、条件判断(1)-eq(相等......
  • VulnHub-Sick0s1.1解法二shellshock漏洞
    免责声明本博客提供的所有信息仅供学习和研究目的,旨在提高读者的网络安全意识和技术能力。请在合法合规的前提下使用本文中提供的任何技术、方法或工具。如果您选择使用本博客中的任何信息进行非法活动,您将独自承担全部法律责任。本博客明确表示不支持、不鼓励也不参与任何形式的......
  • Java编程----利用Map集合设计一个车站上下车的程序
    1.将以下车站对应关系的数据存储到map集合中,key:表示站编号,value:表示站名,并遍历打印(可以不按顺序打印):2.计算地铁票价规则:总行程3站内(包含3站)收费3元,3站以上但不超过5站(包含5站)的收费4元,5站以上的,在4元的基础上,每多1站增加......
  • Java编程学习五
    一、数组的缺陷:二、集合框架三、Vector类四、ArrayList集合五、LinkedList集合六、泛型七、HashSet八、HashMap一、数组的缺陷:1.数组存在定容问题,一旦定义长度,就固定了容量,有时候定义的数据量不一定,很难保证容量不越出;如果需要存储更多或更少的元素,可能需要创建一个新......