目录
shell脚本部分参照:Linux Shell脚本学习指南http://c.biancheng.net/shell/
进行学习,过程中对脚本进行编写运行,部分脚本粘贴出执行结果。
1.指定脚本解析器
#!/bin/bash
cat /etc/
通过 cat /etc/shells 查看
/bin/sh
/bin/bash
/sbin/nologin
/bin/dash
/bin/tcsh
/bin/csh
2.$
引用变量
2."" 与'' 及``区别
'不执行 $element'
"执行 $element,会执行命令"
单引号和双引号的区别
定义变量时,变量的值可以由单引号' '包围,也可以由双引号" "包围
- 以单引号' '包围变量的值时,单引号里面是什么就输出什么,即使内容中有变量和命令(命令需要反引起来)也会把它们原样输出。
这种方式比较适合定义显示纯字符串的情况,即不希望解析变量、命令等的场景。
- 以双引号" "包围变量的值时,输出时会先解析里面的变量和命令,
而不是把双引号中的变量名和命令原样输出。这种方式比较适合字符串中
附带有变量和命令并且想将其解析后再输出的变量定义。
- ``将中间直接解析成指令执行,在获取脚本中获取执行结果很有用 如下:
hostname_=`hostname`
echo $hostname_
- 建议:如果变量的内容是数字,那么可以不加引号;如果真的需要原样输出就加单引号;其他没有特别要求的字符串等最好都加上双引号,定义变量时加双引号是最常见的使用场景。
3.定义变量
Shell 支持以下三种定义变量的方式:
variable=value
variable='value'
variable="value"
variable 是变量名,value 是赋给变量的值。
注意,赋值号=的周围不能有空格,这可能和你熟悉的大部分编程语言都不一样。
如果 value 不包含任何空白符(例如空格、Tab 缩进等),那么可以不使用引号;
如果 value 包含了空白符,那么就必须使用引号包围起来。使用单引号和使用双引号也是有区别的。
注意,赋值号=的周围不能有空格
4.将命令的结果赋值给变量
Shell 也支持将命令的执行结果赋值给变量,常见的有以下两种方式:
variable=`command`
variable=$(command)
第一种方式把命令用反引号` `(位于 Esc 键的下方)包围起来,反引号和单引号非常相似,容易产生混淆,所以不推荐使用这种方式;
***第二种方式把命令用$()包围起来,区分更加明显,所以推荐使用这种方式。
5.只读变量
使用 readonly 命令可以将变量定义为只读变量,只读变量的值不能被改变。
修改只读变量报告异常:line n: e1: readonly variable
6.使用 unset 命令可以删除变量。语法:
unset variable_name
变量被删除后不能再次使用;unset 命令不能删除只读变量。
7.变量作用域
变量的命名时:变量的名字必须以字母或者下划线开头,不能以数字开头
Shell 变量的作用域可以分为三种:
有的变量可以在当前 Shell 会话中使用,这叫做全局变量(global variable);
有的变量只能在函数内部使用,这叫做局部变量(local variable);
而有的变量还可以在其它 Shell 中使用,这叫做环境变量(environment variable)。
全局变量
全局变量的作用范围是当前的 Shell 会话,而不是当前的 Shell 脚本文件,它们是不同的概念。打开一个 Shell 窗口就创建了一个 Shell 会话,打开多个 Shell 窗口就创建了多个 Shell 会话,每个 Shell 会话都是独立的进程,拥有不同的进程 ID。在一个 Shell 会话中,可以执行多个 Shell 脚本文件,此时全局变量在这些脚本文件中都有效。
局部变量
Shell 也支持自定义函数,但是 Shell 函数和 C/C++、Java 等其他编程语言函数的一个不同点就是:在 Shell 函数中定义的变量默认也是全局变量,它和在函数外部定义变量拥有一样的效果
#!/bin/bash
function func(){
a=99
echo "函数中打印变量a ${a}"
}
echo "调用函数打印局部变量"
func
echo "输出函数内部的变量"
echo "${a}"
exit 0
数据出结果:
调用函数打印局部变量
函数中打印变量a 99
输出函数内部的变量
99
- a 是在函数内部定义的,但是在函数外部也可以得到它的值,证明它的作用域是全局的,而不是仅限于函数内部。
- 要想变量的作用域仅限于函数内部,那么可以在定义时加上local命令,此时该变量就成了局部变量。请看下面的代码:
~
#!/bin/bash
function func(){
local a=99
echo "函数中打印变量a ${a}"
}
echo "调用函数打印局部变量"
func
echo "输出函数内部的变量"
echo "${a}"
exit 0
环境变量
全局变量只在当前 Shell 会话中有效,如果使用export命令将它导出,那么它就在所有的子 Shell 中也有效了,这称为“环境变量”。
环境变量被创建时所处的 Shell 被称为父 Shell,如果在父 Shell 中再创建一个 Shell,则该 Shell 被称作子 Shell。当子 Shell 产生时,它会继承父 Shell 的环境变量为自己所用,所以说环境变量可从父 Shell 传给子 Shell。不难理解,环境变量还可以传递给孙 Shell。
注意,环境变量只能向下传递而不能向上传递,即“传子不传父”。~
通过exit命令可以一层一层地退出 Shell。
8.shell位置参数
定义 Shell 函数时不能带参数,但是在调用函数时却可以传递参数,这些传递进来的参数,在函数内部就也使用$n的形式接收,例如,$1 表示第一个参数,$2 表示第二个参数,依次类推。n区间[1,x]
这种通过$n的形式来接收的参数,在 Shell 中称为位置参数。
在讲解变量的命名时,我们提到:变量的名字必须以字母或者下划线开头,不能以数字开头;但是位置参数却偏偏是数字,这和变量的命名规则是相悖的,所以我们将它们视为“特殊变量”。
shell脚本传递参数
#/bin/bash
#dev yjh
echo "I am first var ${1}"
echo "I am second var ${2}"
脚本执行:
./varInput.sh 1 2
I am first var 1
I am second var 2
方法传递参数
#/bin/bash
#dev yjh
echo "I am first var ${1}"
echo "I am second var ${2}"
echo "${0}"
function f1(){
echo "var 1 ${1}"
echo "var 2 ${2}"
}
f1 4 5
exit 0
执行结果
[root@com dev]# ./varInput.sh 2 3
I am first var 2
I am second var 3
./varInput.sh
var 1 4
var 2 5
注意事项
如果参数个数太多,达到或者超过了 10 个,那么就得用${n}的形式来接收了,例如 ${10}、${23}。{ }的作用是为了帮助解释器识别参数的边界,这跟使用变量时加{ }是一样的效果。
特征变量
Shell 特殊变量及其含义 | |
变量 | 含义 |
$0 | 当前脚本的文件名。 |
$n(n≥1) | 传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是 $1,第二个参数是 $2。 |
$# | 传递给脚本或函数的参数个数。 |
$* | 传递给脚本或函数的所有参数。 |
$@ | 传递给脚本或函数的所有参数。当被双引号" "包含时,$@ 与 $* 稍有不同,我们将在《Shell $*和$@的区别》一节中详细讲解。 |
$? | 上个命令的退出状态,或函数的返回值,我们将在《Shell $?》一节中详细讲解。 |
$$ | 当前 Shell 进程 ID。对于 Shell 脚本,就是这些脚本所在的进程 ID。 |
脚本案例
脚本接收参数
#/bin/bash
#dev yjh
echo "I am first var ${1}"
echo "I am second var ${2}"
echo "shell脚本文件名${0}"
echo "shell 脚本传入的参数个数 ${#}"
echo "shell 传入的所有参数 ${*}"
echo "shell 传入所有产生 ${@}"
echo "上个命令执行完成返回状态 $?"
function f1(){
echo "var 1 ${1}"
echo "var 2 ${2}"
}
f1 4 5
echo "f1 函数调用完成 返回值 ${?}"
echo "当前脚本pid ${$}"
exit 0
执行结果
./varInput.sh 234 234 34 4 434
I am first var 234
I am second var 234
shell脚本文件名./varInput.sh
shell 脚本传入的参数个数 5
shell 传入的所有参数 234 234 34 4 434
shell 传入所有产生 234 234 34 4 434
上个命令执行完成返回状态 0
var 1 4
var 2 5
f1 函数调用完成 返回值 0
当前脚本pid 1946
函数接收参数及参数定位
#/bin/bash
#dev yjh
echo "I am first var ${1}"
echo "I am second var ${2}"
echo "shell脚本文件名${0}"
echo "shell 脚本传入的参数个数 ${#}"
echo "shell 传入的所有参数 ${*}"
echo "shell 传入所有参数 ${@}"
echo "上个命令执行完成返回状态 $?"
function f1(){
echo "fun first var is ${1}"
echo "fun second var is ${2}"
echo "fun传入的参数个数 ${#}"
echo "fun 所有参数 ${*}"
echo "shell 传入所有参数 ${@}"
echo "上个命令执行完成返回状态 $?"
}
f1 4 5
echo "f1 函数调用完成 返回值 ${?}"
echo "当前脚本pid ${$}"
exit 0
$@ 与 $* 区别
当 $* 和 $@ 不被双引号" "包围时,它们之间没有任何区别,都是将接收到的每个参数看做一份数据,彼此之间以空格来分隔。
但是当它们被双引号" "包含时,就会有区别了:
- "$*"会将所有的参数从整体上看做一份数据,而不是把每个参数都看做一份数据。
- "$@"仍然将每个参数都看作一份数据,彼此之间是独立的。
比如传递了 5 个参数,那么对于"$*"来说,这 5 个参数会合并到一起形成一份数据,它们之间是无法分割的;而对于"$@"来说,这 5 个参数是相互独立的,它们是 5 份数据。
如果使用 echo 直接输出"$*"和"$@"做对比,是看不出区别的;但如果使用 for 循环来逐个输出数据,立即就能看出区别来。
脚本案例
#!/bin/bash
#dev by yjh
#${*} 获取入参的所有参数,但是当做整体
echo "打印每个参数 "
for var in "${*}"
do
echo ${var}
done
#${@}获取入参所有参数,以空格隔开,各个参数独立
echo "打印每个参数2 "
for var in "${@}"
do
echo ${var}
done
exit 0
执行结果:
./forIn.sh 1 23 44 4 55
打印每个参数
1 23 44 4 55
打印每个参数2
1
23
44
4
55