Shell学习笔记

变量的基本使用

# 定义变量,并且使用变量
# 默认为字符串,但单引号和双引号有不同
# 字符串中无空格时,直接不加引号也可以使用
variable=value
variable='value'
variable="value"
echo "This is $variable"

#{}是为了给变量划定界限
skill="java"
echo "I am goot at ${skill}script" 

# 为变量重新赋值
url="zhangyitian.com"
echo $url
url="llll.com"
echo $url

# 双引号和单引号的区别
# 1. 单引号中的值原样输出
# 2. 双引号则解析变量
# 建议:
# 如果变量的内容是数字,那么可以不加引号;
# 如果真的需要原样输出就加单引号;
# 其他没有特别要求的字符串等最好都加上双引号
url="zhangyitian.com"
website1='This is a website ${url}'
website2="This is a website2 ${url}"
echo $website1
echo $website2
# echo:
# This is a website ${url}
# This is a website2 zhangyitian.com

# 将命令的执行结果赋值给变量
# variable=`command` # 不推荐
# variable=$$(command) # 推荐使用
mkdir code
cd code
echo "hello world" > log.txt # > 为覆盖 >> 为追加
log=$(cat log.txt) # 将cat输出的结果赋值给log变量
echo $log

# 只读变量,值不能被改变
myUrl="zhangyitian.com"
readonly myUrl
# myUrl="lllll.com"
# echo: /data/1060398609: line 48: myUrl: readonly variable

# 删除变量
url="ddddd.com"
unset url # unset 命令不能删除只读变量
echo $url # echo nothing

变量的作用域

##### 变量的作用域
# shell变量的作用域有三种:
# 全局变量:global variable:可以在整个shell会话中使用,
# 局部变量:local $variable:一个函数内部使用
# 环境变量:environment variable:可以在不同的shell中使用

## 全局变量

# 在shell中定义的变量,默认就是全局变量,可以在整个shell会话中使用
# 这里强调的是shell绘画,而不是shell脚本
# 例如打开两个不同的终端,为两个不同的shell会话,每个会话是独立的进程,拥有不同的ID
# 但在一个shell会话中可以运行多个shell脚本,此时全局变量在这些脚本中有效
# 例如两个shell脚本,内容如下

# a.sh
echo $a
b=200

# b.sh
echo $b

# 打开一个shell终端,变量你b在b.sh中也有效


# 局部变量
# shell也支持自定义函数,但函数中定义的变量默认也是全局变量
function func() {
    a=99
}
func # 调用函数
echo $a

# 使用局部变量时,需要加上local命令
function func2(){
    local b=88
}
func2
echo $b # 输出结果为空,表示调用无效

# 环境变量
# 全局变量在当前shell中有效,但在不同shell中就无效了。
# 如果需要在子shell中可用,则需要使用export导出后,子shell可以继承该变量
# 建立一个新shell的方式可以使用
# bash 命令

a=22
echo "original a is: " $a

bash # 进入子shell
echo "1. sub a is: " $a

exit # 退出子shell

export a # 设置环境变量
bash # 进入子shell
echo "2. sub a is: " $a
exit # 退出子shell

位置变量:

#### 位置变量
# 运行 Shell 脚本文件时我们可以给它传递一些参数,这些参数在脚本文件内部可以使用$n的形式来接收,
# 例如,$1 表示第一个参数,$2 表示第二个参数,依次类推。

# 同样,在调用函数时也可以传递参数。Shell 函数参数的传递和其它编程语言不同,没有所谓的形参和实参,
# 在定义函数时也不用指明参数的名字和数目。换句话说,定义 Shell 函数时不能带参数,
# 但是在调用函数时却可以传递参数,这些传递进来的参数,在函数内部就也使用$n的形式接收,
# 例如,$1 表示第一个参数,$2 表示第二个参数,依次类推。

# 这种通过$n的形式来接收的参数,在 Shell 中称为位置参数。

# 1. 给脚本文件传递位置参数

# 编写:/test.sh
echo "language: $1"
echo "URL: $2"

# 运行test.sh脚本文件
#./test.sh shell "zhangyitian.com"

# 2. 给函数传递位置变量
function func3() {
    echo "language: $1"
    echo "URL: $2"
}

func3 "shell" "dfdklsfd.com"

# echo
# language: shell
# URL: dfdklsfd.com

shell特殊变量

图片来自:http://www.runoob.com/linux/linux-shell-passing-arguments.html

#!/bin/bash

### shell特殊变量
# 位置变量$n是特殊变量的一种,
# 其他的几个特殊变量:$#、$*、$@、$?、$$。

# 编写test.sh文件
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

function func() {
    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: $#"
}

func shell linux.com

$*和$@的区别:

#### $*和$@的区别

# 当 $* 和 $@ 不被双引号" "包围时,它们之间没有任何区别,
# 都是将接收到的每个参数看做一份数据,彼此之间以空格来分隔。

# 但是当它们被双引号" "包含时,就会有区别了:
# "$*"会将所有的参数从整体上看做一份数据,而不是把每个参数都看做一份数据。
# "$@"仍然将每个参数都看作一份数据,彼此之间是独立的。

# 比如传递了 5 个参数,那么对于"$*"来说,这 5 个参数会合并到一起形成一份数据,
# 它们之间是无法分割的;而对于"$@"来说,这 5 个参数是相互独立的,它们是 5 份数据。

# 如果使用 echo 直接输出"$*"和"$@"做对比,是看不出区别的;
# 但如果使用 for 循环来逐个输出数据,立即就能看出区别来。

# 这里使用函数测试

function func1() {
    echo "print echo parameters from \"\$*\""
    for var in "$*"
    do
      echo "$var"
    done
}

function func2() {
    echo "print echo parameters from \"\$@\""
    for var in "$@"
    do
        echo "$var"
    done  
}

func1 a b c d

func2 a b c d 

# echo 
# print echo parameters from "$*"
# a b c d
# print echo parameters from "$@"
# a
# b
# c
# d

关于$?的使用:

# $? 是一个特殊变量,用来获取上一个命令的退出状态,或者上一个函数的返回值。
# 所谓退出状态,就是上一个命令执行后的返回结果。
# 退出状态是一个数字,一般情况下,大部分命令执行成功会返回 0,失败返回 1,

# 1. 获取上一个命令的退出状态
# 我们使用两个脚本文件来演示。

# 先编写下面的代码,并保存为 a.sh:
if [$1 == 100]
then 
    return 0
else
    return 1
fi

# 再编写下面的代码,并保存为 b.sh:
echo $?

# 先运行 a.sh,传递参数 100,然后再运行 b.sh,结果如下:
./a.sh 100
./b.sh
# echo 
0

# 2. 获取函数的返回值
function add() {
    return $(expr $1 + $2) # 调用了一个函数
}

add 23 40
echo $? # 输出函数的返回值

# echo 63

字符串操作

##### shell字符串
# 字符串可以由单引号' '包围,也可以由双引号" "包围,也可以不用引号。
# 它们之间是有区别的,稍后我们会详解。

# 下面我们说一下三种形式的区别:

# 1) 由单引号' '包围的字符串:
# 任何字符都会原样输出,在其中使用变量是无效的。
# 字符串中不能出现单引号,即使对单引号进行转义也不行。

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

# 3) 不被引号包围的字符串
# 不被引号包围的字符串中出现变量时也会被解析,这一点和双引号" "包围的字符串一样。
# 字符串中不能出现空格,否则空格后边的会作为其他变量或者字符串解析。

n=74
str1=zhangyitian.com$n 
str2="shell \"script\" $n"
str3='zhangyitian.com $n'

echo $str1
echo $str2
echo $str3

# echo:
# _> zhangyitian.com74
# shell "script" 74
# zhangyitian.com $n


#### 获取字符串长度
# ${#string_name} 

str="http://zhangyitian.com"
echo ${#str}
# echo 22

#### 字符串的拼接

# 在 Shell 中你不需要使用任何运算符,将两个字符串并排放在一起就能实现拼接,非常简单粗暴
name="shell"
url="zhangyitian.com"

str1=$name$url #中间不能有空格
str2="$name $url"  #如果被双引号包围,那么中间可以有空格
str3=$name": "$url #中间可以出现别的字符串
str4="$name: $url" #这样写也可以
str5="${name}script: ${url}index.html" #这个时候需要给变量名加上大括号

echo $str1
echo $str2
echo $str3
echo $str4
echo $str5

# shellzhangyitian.com
# shell zhangyitian.com
# shell: zhangyitian.com
# shell: zhangyitian.com
# shellscript: zhangyitian.comindex.html

字符串的截取:

### 字符串的截取

# Shell 截取字符串通常有两种方式:从指定位置开始截取和从指定字符(子字符串)开始截取。

##### 从指定位置截取
# 这种方式需要两个参数:除了指定起始位置,还需要截取长度,才能最终确定要截取的字符串。

# 既然需要指定起始位置,那么就涉及到计数方向的问题,到底是从字符串左边开始计数,
# 还是从字符串右边开始计数。答案是 Shell 同时支持两种计数方式。


# 1) 从字符串左边开始计数
# 格式如下: 
${string: start:length}

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

url="zhangyitian.com"
echo ${url: 2: 9}
# echo:angyitian

echo ${url: 2} # 省略length,直接到字符串结束
# echo: angyitian.com

## 2) 从右边开始计数
# 如果想从字符串的右边开始计数,那么截取字符串的具体格式如下:
# ${string: 0-start: length}

# 同第 1) 种格式相比,第 2) 种格式仅仅多了0-,这是固定的写法,专门用来表示从字符串右边开始计数。


# 这里需要强调两点:
# 从左边开始计数时,起始数字是 0(这符合程序员思维);
# 从右边开始计数时,起始数字是 1(这符合常人思维)。计数方向不同,起始数字也不同。
# 不管从哪边开始计数,截取方向都是从左到右。

url="zhangyitian.com"
echo "url's length is:" ${#url}
echo ${url: 0-13: 9}
echo ${url: 0-13} # 省略length

# echo:
# angyitian
# angyitian.com

#### 从指定字符(子字符串)开始截取

# 1) 使用 # 号截取右边字符
# 使用#号可以截取指定字符(或者子字符串)右边的所有字符,具体格式如下:
${string#*chars}

# 其中,string 表示要截取的字符,chars 是指定的字符(或者子字符串),
# *是通配符的一种,表示任意长度的字符串。
# *chars连起来使用的意思是:忽略左边的所有字符,直到遇见 chars(chars 不会被截取)。
url="http://zhangyitian.com:jiangshanshan"
echo ${url#*:}
# echo: jiangshanshan
# 下面的命名得到相同的结果
echo ${url#*com:}
echo ${url#*.com:}

# 如果不需要忽略 chars 左边的字符,那么也可以不写*,例如:
echo ${url#http}

# 注意,以上写法遇到第一个匹配的字符(子字符串)就结束了。例如:
echo ${url#*/}
# /zhangyitian.com:jiangshanshan

# 如果希望直到最后一个指定字符(子字符串)再匹配结束,那么可以使用##,具体格式为:
echo ${url##*/}
# zhangyitian.com:jiangshanshan

### 2) 使用 % 截取左边字符

# 使用%号可以截取指定字符(或者子字符串)左边的所有字符,具体格式如下:
# ${string%char*}

# 请注意*的位置,因为要截取 chars 左边的字符,而忽略 chars 右边的字符,所以*应该位于 chars 的右侧。
# 其他方面%和#的用法相同
echo ${url%/*}
echo ${url%%/*}

str="--aa+++aa@@@"
echo ${str%aa*}
echo ${str%%aa*}
# http:/
# http:
# --aa+++
# --

数组操作

###### shell中的数组
# Shell 也支持数组。数组(Array)是若干数据的集合,其中的每一份数据都称为元素(Element)。
# 下标Shell 并且没有限制数组的大小,理论上可以存放无限量的数据。
# 和C语言类似,Shell 数组元素的下标也是从 0 开始计数。
# 获取数组中的元素要使用下标[ ],下标可以是一个整数,也可以是一个结果为整数的表达式;当然,下标必须大于等于 0。
# 常用的 Bash Shell 只支持一维数组,不支持多维数组。


###Shell 数组的定义
# 在 Shell 中,用括号( )来表示数组,数组元素之间用空格来分隔。
# 由此,定义数组的一般形式为:
# array_name=(ele1 ele2 ele3 ... elem)
nums=(1 2 3 4 5 6)

# Shell 是弱类型的,它并不要求所有数组元素的类型必须相同,例如:
arr=(20 56 "http://c.biancheng.net/shell/")

# Shell 数组的长度不是固定的,定义之后还可以增加元素。
nums[6]=88 

#### 获取数组元素
# 获取数组元素的值,一般使用下面的格式:
# ${array_name[index]}
n=${nums[2]}
echo $n

# 使用@或*可以获取数组中的所有元素,例如:
echo ${nums[*]}
echo ${nums[@]}

# 1 2 3 4 5 6 88
# 1 2 3 4 5 6 88

Shell获取字符串长度:

#### shell获取shell的长度
# 利用@或*,可以将数组扩展成列表,然后使用#来获取数组元素的个数,格式如下:
${array_name[@]}
${array_name[*]}
# 其中 array_name 表示数组名。两种形式是等价的,选择其一即可。

# 如果某个元素是字符串,还可以通过指定下标的方式获得该元素的长度,如下所示:
${#arr[2]}

nums=(3 23 4 23 fjdslfjsdl)
echo ${#nums[*]} # 5

# 
nums[5]="zhangyitian.com"
echo ${nums[5]} # zhangyitian.com
echo ${#nums[*]} # 6
echo ${#nums[5]} # 15

unset nums[1]
echo ${#nums[*]} # 5
echo ${nums[*]} # 3 4 23 fjdslfjsdl zhangyitian.com

数组的合并:

### shell数组的合并

# Shell 数组拼接(数组合并),就是将两个数组连接成一个数组。
# 拼接数组的思路是:先利用@或*,将数组扩展成列表,然后再合并到一起。

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

# 两种方式是等价的,选择其一即可。其中,array1 和 array2 是需要拼接的数组,
# array_new 是拼接后形成的新数组。

array1=(33 44)
array2=(55 66)
array_new=(${array1[*]} ${array2[*]})
echo ${array_new[*]}

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

删除数组元素:

#### shell删除数组元素

# 在 Shell 中,使用 unset 关键字来删除数组元素,具体格式如下:
unset array_name[index]

# 删除整个数组
unset array_name

arr=(33 44 55 zhangyitian.com)
unset arr[1]
echo ${arr[*]}

unset arr
echo ${arr[*]}

shell内建命令:

Shell 基本运算符

Shell 和其他编程语言一样,支持多种运算符,包括:

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

算术运算符

#!/bin/bash

###### shell基本运算符
# expr 是一款表达式计算工具,使用它能完成表达式的求值操作

### 算术运算符

a=10
b=20

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`
echo "a/b:" $val

val=`expr $a % $b`
echo "a%b:" $val

if [ $a == $b ] # 注意空格的使用
then
    echo "a=b"
elif [ $a != $b ]
then
    echo "a!=b"
fi

关系运算符

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

下表列出了常用的关系运算符,假定变量 a 为 10,变量 b 为 20:

布尔运算符

下表列出了常用的布尔运算符,假定变量 a 为 10,变量 b 为 20:

逻辑运算符

以下介绍 Shell 的逻辑运算符,假定变量 a 为 10,变量 b 为 20:

字符串运算符

下表列出了常用的字符串运算符,假定变量 a 为 "abc",变量 b 为 "efg":

文件测试运算符

文件测试运算符用于检测 Unix 文件的各种属性。

属性检测描述如下:

这部分图片来自:http://www.runoob.com/linux/linux-shell-passing-arguments.html

echo命令

#!/bin/bash

### echo命令
# 1. 普通字符串
echo "zhangytiian.cn" # zhangytiian.cn

# 2. 转义字符
echo "\"It is a test\"" # "It is a test"

# 3. 显示变量值
val="http://"
echo "$val zhangytiian.com" # http:// zhangytiian.com

# 4.显示换行
echo -e "Ok \n Thank you"
# Ok 
#  Thank you

# 5. 不换行
echo -e "OK \c"
echo "Thank you" # OK Thank you

# 6. 显示结构定向至文件
echo "This is a test" > test.txt
cat test.txt # This is a test

# 7.原样输出字符串
echo '$name\"' # $name\"

# 8. 显示命令执行结果
echo `date` # Fri Mar 15 16:11:12 CST 2019

文中未注明的图片参考自:图片来自:http://c.biancheng.net/view/806.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值