shell结构

注释

井号#,多行就打多个#,没必要记那些花里胡哨的多行注释

范例

#!/bin/bash
#!是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行

# Copyright (c) http://www.codebaoku.com/shell/
Shell 脚本中所有以#开头的都是注释,#!开头的除外。

echo "What is your name?"
echo 命令用于向标准输出文件(Standard Output,stdout,一般就是指显示器)输出文本。

read PERSON
read 命令用来从标准输入文件(Standard Input,stdin,一般就是指键盘)读取用户输入的数据。

echo "Hello, $PERSON"
输出变量 PERSON 的内容。注意在变量名前边要加上$,否则变量名会作为字符串的一部分处理。

运行脚本

作为可执行程序运行

./test.sh

作为解释器参数运行

bash test.sh

检测是否开启了新进程:

#!/bin/bash
echo $$  #输出当前进程PID

以上两种方式是以不同进程运行的

通过 source 命令运行

source 是 Shell 内置命令的一种,它会读取脚本文件中的代码,并依次执行所有语句。

source filename
source ./test.sh

并且,当前进程和运行Shell脚本的进程是同一个进程。

系统环境变量

是系统提供的共享变量,如${SHELL},是linux加载shell的配置文件中定义的变量

shell配置文件类型

在这里插入图片描述

环境变量分类

  1. 系统级环境变量:加载全局配置文件的变量,所有用户共享。
  2. 用户级环境变量:加载个人配置文件的变量,共享给当前用户使用,只给登录用户。

查看系统环境变量

env

查看所有环境变量

set

常用环境变量

在这里插入图片描述

变量

  1. Shell脚本在定义变量时不需要指明类型,直接赋值就可以。
  2. 在 Bash shell 中,每一个变量的值都是字符串,无法直接进行数值运算。
  3. 也可以使用 Shell declare 关键字显式定义变量的类型,但在一般情况下没有这个需求,Shell 开发者在编写代码时自行注意值的类型即可。
  4. 等号两边不可以有空格。

单引号,双引号的区别

  1. 以单引号’ '包围变量的值时,单引号里面是什么就输出什么,即使内容中有变量和命令(命令需要反引起来)也会把它们原样输出。这种方式比较适合定义显示纯字符串的情况,即不希望解析变量、命令等的场景。

  2. 以双引号" "包围变量的值时,输出时会先解析里面的变量和命令,而不是把双引号中的变量名和命令原样输出。这种方式比较适合字符串中附带有变量和命令并且想将其解析后再输出的变量定义。

  3. 建议:原样输出用单,没别的事就用双。

定义变量

variable=value  无需记忆
variable='value' 

# 推荐用双引号,弱水三千只取一瓢,只记忆这种即可
variable="value"

使用变量

author="张三" 无需记忆
echo $author 无需记忆


推荐给所有变量加上花括号{ },这是个良好的编程习惯。
echo ${author}

修改变量值

url="http://www.codebaoku.com"
echo ${url}

# 第二次对变量赋值时不能在变量名前加$,只有在使用变量时才能加$。
url="http://www.codebaoku.com/shell/"
echo ${url}

命令结果赋值给变量

$() 仅在 Bash Shell 中有效,而反引号可在多种 Shell 中使用。

variable=`command` # 反引号,无需记忆

variable=$(command) # 推荐

只读变量

使用 readonly 命令可以将变量定义为只读变量,只读变量的值不能被改变。

#!/bin/bash

myUrl="http://www.codebaoku.com/shell/"
readonly myUrl

全局变量

使用export命令可以将变量定义为全局变量,可以让子环境使用

#!/bin/bash

myUrl="http://www.codebaoku.com/shell/"
export myUrl
sh ./bash2.sh

-------------------------
#!/bin/bash

echo "${myUrl}"

删除变量

  1. 变量被删除后不能再次使用
  2. unset 命令不能删除只读变量。
unset variable_name

自定义系统级环境变量

  1. 当用户进入shell环境时,会初始化/etc/profile里的环境变量给所有shell程序使用
  2. 只要是所有shell命令都要用到的变量就可以定义在/etc/profile

编辑

  1. 定义key=val并导出为环境变量export key=val
  2. 重载环境变量source /etc/profile
  3. 使用

位置参数

  1. 运行 Shell 脚本文件时可以传递参数,这些参数在脚本文件内部可以使用$n的形式来接收,例如,$1 表示第一个参数,$2 表示第二个参数,依次类推。
  2. Shell 函数参数的传递和其它编程语言不同,没有所谓的形参和实参,在定义函数时也不用指明参数的名字和数目。

给脚本文件传递位置参数

#!/bin/bash

echo "Language: $1"
echo "URL: $2"

# 执行脚本
./test.sh python fuck.com

给函数传递位置参数

#!/bin/bash

#定义函数
function func(){
    echo "Language: $1"
    echo "URL: $2"
}

#调用函数
func C++ http://www.codebaoku.com/cplus/

如果参数个数太多,达到或者超过了 10 个,那么就得用${n}的形式来接收了,例如 10 、 {10}、 10{23}

echo -n "What is your name?"
read name

function echoName(){
    echo "your name is ${1}"
}

echoName ${name}

特殊变量

分别是:$#$*$n$@$?$$
Shell 特殊变量及其含义
变量 含义
$0 当前脚本的文件名。
$n(n≥1) 传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是 $1,第二个参数是 $2。
$# 传递给脚本或函数的参数个数。
$* 传递给脚本或函数的所有参数。如果带双引号时,会将所有参数拼接得到一个字符串。
$@ 传递给脚本或函数的所有参数。当被双引号" "包含时,$@ 与 $* 稍有不同。
$? 上个命令的退出状态,或函数的返回值。
$$ 当前 Shell 进程 ID。对于 Shell 脚本,就是这些脚本所在的进程 ID。
#!/bin/bash

echo "Process ID: $$"
echo "File Name: $0"
echo "First Parameter : $1"
echo "Second Parameter : $2"
echo "All parameters 1: $@"
echo "All parameters 2: $*"
echo "Total: $#"


>>> ./test.sh Shell Linux

Process ID: 5943
File Name: bash
First Parameter : Shell
Second Parameter : Linux
All parameters 1: Shell Linux
All parameters 2: Shell Linux
Total: 2

字符串

str1=www.codebaoku.com 不推荐

str2="shell script"
如果其中包含了某个变量,那么该变量会被解析(得到该变量的值),而不是原样输出。
字符串中可以出现双引号,只要它被转义了就行。

str3='菜鸟教程'
任何字符都会原样输出,在其中使用变量是无效的。
字符串中不能出现单引号,即使对单引号进行转义也不行。
#!/bin/bash

n=74
str1=www.codebaoku.com$n 
str2="shell \"script\" $n"
str3='编程宝库 $n'

echo $str1
echo $str2
echo $str3

--------------------------
www.codebaoku.com74
shell "script" 74
编程宝库 $n

计算长度

${#string_name}

字符串拼接

str5="${name}Script: ${url}index.html"

字符串截取

${string: start :length}
其中,string 是要截取的字符串,start 是起始位置(从左边开始,从 0 开始计数),length 是要截取的长度(省略的话表示直到字符串的末尾)。

数组

只支持一维数组

arr=(20 56 "http://c.biancheng.net/shell/")ages=([3]=24 [5]=19 [10]=12) # 指定这些index位置的值

追加

arr[5]=1 # index可以溢出,触发扩容

获取 Shell 数组元素

${array_name[index]}

获取所有元素
${nums[*]}
${nums[@]}

获取数组长度

${#array_name[*]} 或者 ${#array_name[@]}

数组拼接

array_new=(${array1[@]}  ${array2[@]})
array_new=(${array1[*]}  ${array2[*]})

删除数组元素

unset nums[0]

基本运算符

  1. 原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk 和 expr,expr 最常用。
  2. expr 是一款表达式计算工具,使用它能完成表达式的求值操作。
  3. 两个数相加使用的是反引号 ` 而不是单引号 ',也可以使用$()
  4. 表达式和运算符之间要有空格

算术运算符

乘号(*)前边必须加反斜杠()才能实现乘法运算;

运算符 说明 举例
+ 加法 `expr $a + $b` 结果为 30。
- 减法 `expr $a - $b` 结果为 -10。
* 乘法 `expr $a \* $b` 结果为  200。
/ 除法 `expr $b / $a` 结果为 2。
% 取余 `expr $b % $a` 结果为 0。
= 赋值 a=$b 将把变量 b 的值赋给 a。
== 相等。用于比较两个数字,相同则返回 true。 [ $a == $b ] 返回 false。
!= 不相等。用于比较两个数字,不相同则返回 true。 [ $a != $b ] 返回 true。

关系运算符

关系运算符只支持数字,不支持字符串,除非字符串的值是数字。

运算符 说明 举例
-eq 检测两个数是否相等,相等返回 true。 [ $a -eq $b ] 返回 false。
-ne 检测两个数是否不相等,不相等返回 true。 [ $a -ne $b ] 返回 true。
-gt 检测左边的数是否大于右边的,如果是,则返回 true。 [ $a -gt $b ] 返回 false。
-lt 检测左边的数是否小于右边的,如果是,则返回 true。 [ $a -lt $b ] 返回 true。
-ge 检测左边的数是否大于等于右边的,如果是,则返回 true。 [ $a -ge $b ] 返回 false。
-le 检测左边的数是否小于等于右边的,如果是,则返回 true。 [ $a -le $b ] 返回 true。

布尔运算符

运算符 说明 举例
! 非运算,表达式为 true 则返回 false,否则返回 true。 [ ! false ] 返回 true。
-o 或运算,有一个表达式为 true 则返回 true。 [ $a -lt 20 -o $b -gt 100 ] 返回 true。
-a 与运算,两个表达式都为 true 才返回 true。 [ $a -lt 20 -a $b -gt 100 ] 返回 false。

逻辑运算符

运算符 说明 举例
&& 逻辑的 AND [[ $a -lt 100 && $b -gt 100 ]] 返回 false
|| 逻辑的 OR [[ $a -lt 100 || $b -gt 100 ]] 返回 true

字符串运算符

运算符 说明 举例
= 检测两个字符串是否相等,相等返回 true。 [ $a = $b ] 返回 false。
!= 检测两个字符串是否不相等,不相等返回 true。 [ $a != $b ] 返回 true。
-z 检测字符串长度是否为0,为0返回 true。 [ -z $a ] 返回 false。
-n 检测字符串长度是否不为 0,不为 0 返回 true。 [ -n "$a" ] 返回 true。
$ 检测字符串是否为空,不为空返回 true。 [ $a ] 返回 true。

文件测试运算符

操作符 说明 举例
-b file 检测文件是否是块设备文件,如果是,则返回 true。 [ -b $file ] 返回 false。
-c file 检测文件是否是字符设备文件,如果是,则返回 true。 [ -c $file ] 返回 false。
-d file 检测文件是否是目录,如果是,则返回 true。 [ -d $file ] 返回 false。
-f file 检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。 [ -f $file ] 返回 true。
-g file 检测文件是否设置了 SGID 位,如果是,则返回 true。 [ -g $file ] 返回 false。
-k file 检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。 [ -k $file ] 返回 false。
-p file 检测文件是否是有名管道,如果是,则返回 true。 [ -p $file ] 返回 false。
-u file 检测文件是否设置了 SUID 位,如果是,则返回 true。 [ -u $file ] 返回 false。
-r file 检测文件是否可读,如果是,则返回 true。 [ -r $file ] 返回 true。
-w file 检测文件是否可写,如果是,则返回 true。 [ -w $file ] 返回 true。
-x file 检测文件是否可执行,如果是,则返回 true。 [ -x $file ] 返回 true。
-s file 检测文件是否为空(文件大小是否大于0),不为空返回 true。 [ -s $file ] 返回 true。
-e file 检测文件(包括目录)是否存在,如果是,则返回 true。 [ -e $file ] 返回 true。

函数

可以带function fun() 定义,也可以直接fun() 定义,不带任何参数。
[ function ] funname (){
    action;

	# 参数返回,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值
    [return int;]
}

函数的返回值可以在调用该函数后通过 $? 来获得。

#!/bin/bash
# author:编程宝库
# url:www.codebaoku.com

funWithReturn(){
    echo "这个函数会对输入的两个数字进行相加运算..."
    echo "输入第一个数字: "
    read aNum
    echo "输入第二个数字: "
    read anotherNum
    echo "两个数字分别为 $aNum$anotherNum !"
    return $(($aNum+$anotherNum))
}
funWithReturn
echo "输入的两个数字之和为 $? !"

文件引用

# 等同于import
source filename

输入/输出重定向

命令 说明
command > file 将输出重定向到 file。
command < file 将输入重定向到 file。 本来需要从键盘获取输入的命令会转移到文件读取内容。
command >> file 将输出以追加的方式重定向到 file。
n > file 将文件描述符为 n 的文件重定向到 file。
n >> file 将文件描述符为 n 的文件以追加的方式重定向到 file。
n >& m 将输出文件 m 和 n 合并。
n <& m 将输入文件 m 和 n 合并。
<< tag 将开始标记 tag 和结束标记 tag 之间的内容作为输入。
  1. 标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。
  2. 标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。
  3. 标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。
  4. 默认情况下,command > file 将 stdout 重定向到 file,command < file 将stdin 重定向到 file。
  5. stderr 重定向到 file:command 2>file
  6. 将 stdout 和 stderr 合并后重定向到 file:command 2>&1> file

Here Document

command << delimiter
    document
delimiter

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

wc -l << EOF
    fuck off
    fuck off
    fuck off
EOF
3          # 输出结果为 3 行

wc -l << tmd
> fuck off
> fuck off
> fuck off
> tmd
3

/dev/null 文件

如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null

分支

if condition1
then
    command1
elif condition2 
then 
    command2
else
    commandN
fi

case语句

casein
模式1)
    command1
    command2
    ...
    commandN
    ;;
模式2)
    command1
    command2
    ...
    commandN
    ;;
esac

循环语句

for var in item1 item2 ... itemN
do
    command1
    command2
    ...
    commandN
done

while condition
do
    command
done

until 循环执行一系列命令直至条件为 true 时停止。
until condition
do
    command
done

无限循环

for (( ; ; ))

while true
do
    command
done

break continue(毁三观)

  1. break命令允许跳出所有循环,终止执行后面的所有循环。
  2. continue命令与break命令类似,只有一点差别,它不会跳出所有循环,仅仅跳出当前循环。

echo命令

Shell echo 命令用于字符串的输出

printf 命令

  1. Shell printf 与 echo 类似,用于字符串的输出。
  2. printf 由 POSIX 标准所定义,因此使用 printf 的脚本比使用 echo 移植性好。
printf  format-string  [arguments...]

# format-string为双引号
printf "%d %s\n" 1 "abc"

test 命令(鸡肋,不用记忆)

Shell中的 test 命令用于检查某个条件是否成立,它可以进行数值、字符和文件三个方面的测试。

num1=100
num2=100

if test $[num1] -eq $[num2]
then
    echo '两个数相等!'
else
    echo '两个数不相等!'
fi

read命令

read 是 Shell 内置命令,用来从标准输入中读取数据并赋值给变量

read [-options] [variables]

# 读取三个变量,并且显示提示信息
read -p "Enter some information > " name url age
Shell read 命令支持的选项
选项 说明
-a array 把读取的数据赋值给数组 array,从下标 0 开始。
-d delimiter 用字符串 delimiter 指定读取结束的位置,而不是一个换行符(读取到的数据不包括 delimiter)。
-e 在获取用户输入的时候,对功能键进行编码转换,不会直接显式功能键对应的字符。
-n num 读取 num 个字符,而不是整行字符。
-p prompt 显示提示信息,提示内容为 prompt。
-r 原样读取(Raw mode),不把反斜杠字符解释为转义字符。
-s 静默模式(Silent mode),不会在屏幕上显示输入的字符。当输入密码和其它确认信息的时候,这是很有必要的。
-t seconds 设置超时时间,单位为秒。如果用户没有在指定时间内输入完成,那么 read 将会返回一个非 0 的退出状态,表示读取失败。
-u fd 使用文件描述符 fd 作为输入源,而不是标准输入,类似于重定向。
#!/bin/bash
# 在指定时间内输入密码

if
    read -t 20 -sp "Enter password in 20 seconds(once) > " pass1 && printf "\n" &&  #第一次输入密码
    read -t 20 -sp "Enter password in 20 seconds(again)> " pass2 && printf "\n" &&  #第二次输入密码
    [ $pass1 == $pass2 ]  #判断两次输入的密码是否相等
then
    echo "Valid password"
else
    echo "Invalid password"
fi

(())命令

运算操作符/运算命令说明
((a=10+66) ((b=a-15)) ((c=a+b))这种写法可以在计算完成后给变量赋值。以 ((b=a-15)) 为例,即将 a-15 的运算结果赋值给变量 c。 注意,使用变量时不用加$前缀,(( )) 会自动解析变量名。
a=$((10+66) b=$((a-15)) c=$((a+b))可以在 (( )) 前面加上$符号获取 (( )) 命令的执行结果,也即获取整个表达式的值。以 c=$((a+b)) 为例,即将 a+b 这个表达式的运算结果赋值给变量 c。 注意,类似 c=((a+b)) 这样的写法是错误的,不加$就不能取得表达式的结果。
((a>7 && b==c))(( )) 也可以进行逻辑运算,在 if 语句中常会使用逻辑运算。
echo $((a+10))需要立即输出表达式的运算结果时,可以在 (( )) 前面加$符号。
((a=3+5, b=a+10))对多个表达式同时进行计算。
  1. 双小括号 (( )) 是 Bash Shell 中专门用来进行整数运算的命令,它的效率很高,写法灵活,是企业运维中常用的运算命令。
  2. 在 (( )) 中使用变量无需加上$前缀,(( )) 会自动解析变量名,这使得代码更加简洁,也符合程序员的书写习惯。
  3. 可以使用 获取 ( ( ) ) 命令的结果,这和使用 获取 (( )) 命令的结果,这和使用 获取(())命令的结果,这和使用获得变量值是类似的。

自增(++)和自减(–)运算

echo $((--a))

echo $((++a))

let命令

let 命令和双小括号 (( )) 的用法是类似的,它们都是用来对整数进行运算。

扩展循环

#!/bin/sh
num=100;
total=0;
for((i=0;i<=num;i++));
do
    ((total+=i));
done
echo $total;
# 5050
 
total=0;
i=0;
while((i<=num));
do
    ((total+=i,i++));
done
echo $total;
# 5050
 
if((total>=5050));then
    echo "ok";
fi
# ok

[[]]命令(升级版test)

[[ ]] 剔除了 test 命令的-o和-a选项,你只能使用 || 和 &&(nice!)

[[ expression ]]

if [[ -z $str1 ]] || [[ -z $str2 ]]

支持正则表达式

[[ str =~ regex ]]

if [[ $tel =~ ^1[0-9]{10}$ ]]
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Generalzy

文章对您有帮助,倍感荣幸

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值