shell scripts 学习记录

在这里插入图片描述

1. 环境变量的使用

shell中的环境变量分为env和set两种:

  • set:仅在当前变量shell中成生效.
  • env:仅在当前会话中生效
env        # 查看环境变量
set 
export       # 设置环境变量
unset        # 删除环境变量
$            # 引用变量
=            # 设置变量赋值
#            # 获取变量长度

2. Shell中的数组使用

Array

数组中可以存放多个值,Bash Shell 只支持一维数组,使用语法如下:

array_name=("cxk" 123 "wjk" 'wyf')
echo ${array_name[0]}
echo ${array_name[1]}
echo ${array_name[2]}
echo ${array_name[3]}
echo ${array_name[*]}     # 一行输出所有元素
echo ${#array_name[*]}    # 输出数组的长度 也可以使用${#array_name[@]}

# 执行结果输出为:
cxk
123
wjk
wyf
cxk 123 wjk wyf
4

注意:数组中可以存储不同类型的元素。

关联数组 (理解为python中的字典)

Bash 支持关联数组,可以使用任意的字符串、或者整数作为下标来访问数组元素。使用语法如下:

# declare -A xxx
declare -A array_name
array_name["cxk"]=25
array_name["wyf"]=30
array_name[1949]="10.1"
# 取出关联数组汇总的元素,需要指定key
echo ${array_name["cxk"]}
echo ${array_name["wyf"]}
echo ${array_name[1949]}
echo ${#array_name[@]}   # 数组的长度
echo ${#array_name["cxk"]}  # 某个key对应value的长度 字符型key
echo ${#array_name[1949]}   # 某个key对应value的长度 整数key
echo ${array_name[*]}     # 一行输出所有的value
echo ${!array_name[*]}    # 通过添加!取出所有的key

# 执行结果为:
25
30
10.1
3
2
4
10.1 25 30
cxk wyf 1949
  1. 字典需要根据指定key读取对应的value,且所有类型value的长度都可以通过#提取到。
  2. 输出value的是无序的。

3. shell中的基本运算符

常用的运算符有:

  • 算数运算符
  • 关系运算符
  • 布尔运算符
  • 字符串运算符
  • 文件测试运算符

原生的bash不支持简单的数学运算,可以通过expr实现

#!/bin/bash
a=2
b=4

val=`expr ${a} + ${b}`   
echo "a + b : $val"    
val=`expr ${a} - ${b}`
echo "a - b : ${val}"
val=`expr ${a} \* ${b}`  # 乘法需要注意使用 \*
echo "a * b : ${val}"
val=`expr ${a} / ${b}`   # shell只支持整数运算,这种除不尽的,不同版本的shell结果不一致
echo "a / b: ${tmp}"
val=`expr ${b} / ${a}`
echo "b / a : ${val}"

# 执行结果为:
a + b : 6
a - b : -2
a * b : 8
a / b: 7
b / a : 2
  1. expr 后面表达式需要空格分明,即 $a + $b,而不是$a+$b
  2. 完成的表达式需要用``包含起来,不是单引号,是ESC下面的符号。

4. shell 中流程控制语法

case…esac使用

echo "请输入1到4的数字:"
echo "你输入的数字为:"
read num

case ${num} in
	1) command      # 你输入的数字为1,执行后续的command
	;; # 两个分号
	2) command     
	;;
	3) command
	;;
esac                # 结束符

if else条件中如果:

  • 使用-gt-lteq之类的逻辑操作,那么使用[...]括号
  • 使用<>==之类的计算操作,那么使用((...))括号
# 字符串
read pattern
case "${pattern}" in
	"wjk") echo "这里是王俊凯"
	;;
	"wyf") echo "skr,skr!"
	;;
	"cxk") echo "时长两年半"
	;;
	*)	echo "找不到该明星"      
	;;
esac

注意:用*)来接受其它情况

5. 函数定义与调用

5.1 带返回值的函数

#!/bin/bash
# 函数声明
fun_with_return(){
        echo "这个函数会对输入的两个数字进行相加..."
        echo "输入第一个数字:"
        read first_num
        echo "输入第二个数字:"
        read second_num
        return $((${first_num} + ${second_num}))
}

fun_with_return     # 调用函数
echo "相加的和为:$?!"

-------------------------------------------------------------
# 执行结果得到:
这个函数会对输入的两个数字进行相加...
输入第一个数字:
8
输入第二个数字:
9
相加的和为:17!

5.2 带传参数的函数

#!/bin/bash
# 带传参函数声明
fun_with_parameters(){
        echo "第一个参数为$1"
        echo "第二个参数为$2"
        echo "第10个参数为$10"
        echo "第10个参数为${10}"
        echo "第11个参数为${11}"
        echo "参数总共有$#个"
        echo "直接作为一个字符串打印所有参数$*"

}
# 函数调用,后面直接跟上所传递的参数
fun_with_parameters wo xin 3 4 5 6 7 8 9 fei teng la 

执行结果如下,可以发现第10个参数用{}不用{}的结果是不一样的:

在这里插入图片描述
直接在vim进入该文件,如下图所示,发现$符号只能识别1~9.
$10 不能获取第十个参数,获取第十个参数需要${10}

在这里插入图片描述

n>=10时,需要使用${n}来获取参数。

6. shell 中的输入/输出重定向

需要注意的是文件描述符 0 通常是标准输入(STDIN),1 是标准输出(STDOUT),2 是标准错误输出(STDERR)。

6.1 输出重定向

command1 > file1        # 输出重定向,将command1执行的结果输出到文件file1中(覆盖)
command2 >> file2       # 在末尾换行追加

# 实例,将两个结果先后写到一个文件里去
ls -l > forwardtest.sh
ls >> forwardtest.sh

# 可以看到>>的追加形式,会自动换到当前文件内容的下一行进行追加

在这里插入图片描述

6.2 输入重定向

# 统计forwardtest.sh文件的行数
wc -l < forwardtest.sh       # 读取forwardtest.sh文件内容
# 执行结果为:
19

wc -l forwardtest.sh         # 
# 执行结果为:
19 forwardtest.sh

区别:前者不会输出文件名,后者会输出文件名.

6.3 错误文件重定向

一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件1

  • 标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。
  • 标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。
  • 标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。
command 2>file1     # 将错误信息重定向到file1文件中
command 2>>file1    # 追加


# 希望将stdout和stderr合并输出到指定文件
command > file1 2>&1
或者
command >> file1 2>&1


command < file1 > file2   # 从file1读取,执行command后,将结果输出到file2

6.4 Here Document使用

# 它的作用是将两个 delimiter 之间的内容(document) 作为输入传递给 command。
command << delimiter
    document
delimiter

# 实例:
cat << +
cxk
wjk
wyf
+

# 执行结果为:
cxk
wjk
wyf

解析:

  • cat:表示command,需要执行的命令
  • <<:这是 Here Document 的开始标记,它告诉 Shell 后面会有一个多行文本块。
  • delimiter:可以由用户任意指定,当然一般用EOF比较合适,delimiter用于表示后续文本的开始和结束。
  • cxk wjk wyf:表示多行文本块中的文本内容

执行过程:

  • 当shell遇到<< +,则会从下一行开始读取,将所有行知道遇到+为止的所有内容都是为一个文本块,然后将这个文本块作为输入传递给cat命令,最后由cat命令将该内容块打印到屏幕中

6.5 /dev/null的使用

# 如果希望执行某个命令的输出结果,不显示在屏幕上,那么可以将其重定向为/dev/null
command > /dev/null

# 如果希望屏蔽stdout和stderr
command > /dev/null 2>&1

/dev/null 是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么也读不到。但是 /dev/null 文件非常有用,将命令的输出重定向到它,会起到"禁止输出"的效果。


小坑总结

单引号和双引号输出变量存在的问题

your_name="cxk"
# 使用双引号拼接
name="hello, "${your_name}" !" 
name_1="hello, ${your_name} !"
echo $name  $name_1

# 使用单引号拼接
name_2='hello, '${your_name}' !'
name_3='hello, ${your_name} !'
echo $name_2  $name_3

输出结果如下:

hello, cxk ! hello, cxk !
hello, cxk ! hello, ${your_name} !

显然,在双引号的情况下,${your_name}是能够取出变量中的值.

第三种情况,虽然使用了单引号单引号,但是存在字符串拼接(这里不太理解,我个人感觉两层单引号,也算是双引号了),所以也能够取出${your_name}中的值。而第四种情况name_3中,单引号直接将里面的内容全部当作字符串了,因此直接输出。

condition 括号(())、[]、[[]]使用总结

总体建议:

  • 对于简单的条件判断,使用方括号[]是通用的做法,适用于大多数的 POSIX 兼容 Shell。
  • 对于复杂的条件测试,如模式匹配、逻辑运算等,使用双方括号 [[]] 更为合适,特别是在 Bash Shell 中。
  • 对于数值比较和算术运算,使用双圆括号(())更为合适,它提供了便捷的数值操作。

多行注释

参考Here Document用法,将内容丢给:,然而:不会做任何操作,因此可以充当注释使用,

: >> delimiter
内容
delimiter

# 例如:
: >> COMMENT
内容
COMMENT

$()${}的区别

  • $()用于将一个命令的输出结果作为一个整体来替换。例如,result=$(command) 会将 command 的输出结果存储在 result 变量中。${}可以在变量的值中插入命令的输出结果。
  • 通常情况下,推荐使用$()来进行命令替换,而使用${}来进行变量替换和参数替换。

  1. 菜鸟教程 ↩︎

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值