shell语法
1,配置文件
登陆Linux系统,打开Terminal,使用Shell的时候,系统在背后读取了一大“坨”的配置文件,这些配置文件决定了你的Shell中的变量
/etc/profile
:该文件为系统的每个用户设置环境信息,当用户第一次登录系统时,该文件会被执行。 并从/etc/profile.d目录的配置文件中读取shell的设置;~/.bash_profile
或者~/.bash_login
或者~/.profile
:系统会依次寻找这三个文件,这些是针对当前用户的配置,但是需要注意的是,这三个文件一般不会同时存在,即使同时存在,系统按照这个顺序找到了一个以后,就不会再去读剩下的了;~/.bashrc
:该文件包含了专属于当前登录用户的bash shell的bash信息,当登录以及每次打开新的shell时,该文件都会被读取;/etc/bashrc
:为每一个运行bash shell的用户执行此文件;当bash shell被打开时,该文件被读取。
2,变量
- 内部变量;系统定义,不能修改;
- 环境变量;系统定义,可以修改,可以利用
export
将用户变量转为环境变量; - 用户变量;用户定义,可以定义,玩坏了都没事。
以下这些就是内部变量:
变量名 描述
$# 命令行参数个数
$0 当前程序的名称
$? 前一个命令或函数的返回码
$$ 当前程序的PID
以下这些是我们常用的一些环境变量,一般我们使用env命令查看当前用户的环境变量。
变量名 描述
PATH 表示Shell将到哪些目录中寻找命令或程序
SHELL 当前用户的Shell类型
HOME 当前用户主目录
PS1 基本提示符
用户变量(本地变量)那就比较随性了,你可以自己随意定义,比如:
> str='Hello World'
> echo $str
3,export命令
1)export命令可以将用户变量设置为环境变量,从而可以在子Shell进程中访问该变量。
2)我们在父Shell中输入export str以后,当我们关闭父Shell以后,该环境变量将失效,如果想打开Shell就能立刻设置export,我们可以按照我们的需要,将export str写到上面总结的那一“坨”启动配置文件中,这样就不会因为关闭了父Shell而导致export失效。
3)我们在父Shell中输入export str以后,当我们关闭父Shell以后,该环境变量将失效,如果想打开Shell就能立刻设置export,我们可以按照我们的需要,将export str写到上面总结的那一“坨”启动配置文件中,这样就不会因为关闭了父Shell而导致export失效。
4)你不可以在父Shell中访问子Shell中定义的变量。如果想在父Shell中访问子Shell中定义的变量,可以借助一个临时文件,将局部变量写入临时文件,父Shell读取这个文件,从而达到访问子Shell中定义的变量的目的。
4,条件判断
#!/bin/bash
if test -f testDemo.sh
then
echo "testDemo.sh exists."
fi
if [ -f test.c ]
then
echo "test.c exists."
else
echo "I cannot find exists."
fi
if condition
then
statements
elif condition
then
statements
else
statements
fi
字符串比较 结果
string1 = string2 如果两个字符串相同,结果就为真
string1 != string2 如果两个字符串不同,结果就为真
-n string 如果字符串不为空,则结果为真
-z string 如果字符串为一个空串(null),则结果为真
算术比较 结果
expression1 -eq expression2 如果两个表达式相等,则结果为真
expression1 -ne expression2 如果两个表达式不等,则结果为真
expression1 -gt expression2 如果expression1大于expression2,则为真
expression1 -ge expression2 如果expression1大于等于expression2,则为真
expression1 -lt expression2 如果expression1小于expression2,则为真
expression1 -le expression2 如果expression1小于等于expression2,则为真
!expression 表达式为假,则结果就为真;反之亦然
文件条件测试 结果
-d file 如果文件是一个目录,则为真
-f file 如果文件是一个普通文件,则为真;也可以用来测试文件是否存在
-r file 如果文件可读,则结果为真
-s file 如果文件大小不为0,则结果为真
-w file 如果文件可写,则结果为真
-x file 如果文件可执行,则结果为真
5,循环处理
for foo in Jelly Think Website
do
echo $foo
done
echo "Enter password: "
read pwd
while [ "$pwd" != "root" ]
do
echo "Sorry, try again."
read pwd
done
until condition
do
statements
done
6,分支处理
#!/bin/bash
echo "Is it morning? Please answer yes or no."
read input
case "$input" in
yes ) echo "Good Morning.";;
no ) echo "Good Afternoon.";;
y ) echo "Good Morning.";;
n ) echo "Good Afternoon.";;
* ) echo "Sorry, answer not recognized";;
esac
exit 0
当case语句被执行时,它会把变量input的内容与各字符串依次进行比较。一旦某个字符串与输入匹配成功,case命令就会执行紧随右括号)后面的代码,然后就结束。 在代码中,最后面的*表示匹配任何字符串,我们在写代码时,总是在其它匹配之后再添加一个*以确保如果没有字符串得到匹配,case语句也会执行某个默认动作。
#!/bin/bash
echo "Is it morning? Please answer yes or no."
read input
case "$input" in
yes | y | Yes | YES ) echo "Good Morning.";;
n* | N* ) echo "Good Afternoon.";;
* ) echo "Sorry, answer not recognized.";;
esac
exit 0
上面这段代码,使用了|符号,也就是说,也就是合并了多个匹配模式;同时还使用了*通配符;没有问题,上面的代码运行的很好。
7,函数
#!/bin/bash
sample_text="global variable"
foo()
{
local sample_text="local variable"
echo "Function foo is executing..."
echo $sample_text
}
echo "script starting..."
echo $sample_text
foo
echo "script ended..."
echo $sample_text
exit 0
返回值
[~/shell/function]# cat return.sh
#!/bin/bash
function fun1 {
read -p "enter a: " a
echo -n "print 2a: "
return $[ $a * 2 ]
}
fun1
echo "return value $?"
[~/shell/function]# ./return.sh
enter a: 100
print 2a: return value 200
传递参数
[~/shell/function]# cat ./parameter.sh
#!/bin/bash
if [ $# -ne 3 ]
then
echo "usage: $0 a b c"
exit
fi
fun3() {
echo $[ $1 * $2 * $3 ]
}
result=`fun3 $1 $2 $3`
echo the result is $result
[~/shell/function]# ./parameter.sh 1 2 3
the result is 6
[~/shell/function]# ./parameter.sh 1 2
usage: ./parameter.sh a b c
传递参数
#!/bin/bash # author:菜鸟教程 # url:www.runoob.com funWithParam(){ echo "第一个参数为 $1 !" echo "第二个参数为 $2 !" echo "第十个参数为 $10 !" echo "第十个参数为 ${10} !" echo "第十一个参数为 ${11} !" echo "参数总数有 $# 个!" echo "作为一个字符串输出所有参数 $* !" } funWithParam 1 2 3 4 5 6 7 8 9 34 73
数组变量
[~/shell/function]# cat array.sh
#!/bin/bash
a=(11 12 13 14 15)
echo ${a[*]}
function array(){
echo parameters : "$@"
local factorial=1
for value in "$@"
do
factorial=$[ $factorial * $value ]
done
echo $factorial
}
array ${a[*]}
[~/shell/function]# ./array.sh
11 12 13 14 15
parameters : 11 12 13 14 15
360360
8,通配符
字符 | 含义 | 实例 |
* | 匹配 0 或多个字符 | a*b a与b之间可以有任意长度的任意字符, 也可以一个也没有, 如aabcb, axyzb, a012b, ab。 |
? | 匹配任意一个字符 | a?b a与b之间必须也只能有一个字符, 可以是任意字符, 如aab, abb, acb, a0b。 |
[list] | 匹配 list 中的任意单一字符 | a[xyz]b a与b之间必须也只能有一个字符, 但只能是 x 或 y 或 z, 如: axb, ayb, azb。 |
[!list] | 匹配 除list 中的任意单一字符 | a[!0-9]b a与b之间必须也只能有一个字符, 但不能是阿拉伯数字, 如axb, aab, a-b。 |
[c1-c2] | 匹配 c1-c2 中的任意单一字符 如:[0-9] [a-z] | a[0-9]b 0与9之间必须也只能有一个字符 如a0b, a1b... a9b。 |
{string1,string2,...} | 匹配 sring1 或 string2 (或更多)其一字符串 | a{abc,xyz,123}b a与b之间只能是abc或xyz或123这三个字符串之一。 |
[chengmo@localhost ~
/shell
]$
ls
*.txt
a.txt b.txt
= 设定变量。
$ 作变量或运算替换(请不要与 shell prompt 搞混了)。
> 重导向 stdout。 *
< 重导向 stdin。 *
| 命令管线。 *
& 重导向 file descriptor ,或将命令置于背境执行。 *
( ) 将其内的命令置于 nested subshell 执行,或用于运算或命令替换。 *
{ } 将其内的命令置于 non-named function 中执行,或用在变量替换的界定范围。
; 在前一个命令结束时,而忽略其返回值,继续执行下一个命令。 *
&& 在前一个命令结束时,若返回值为 true,继续执行下一个命令。 *
|| 在前一个命令结束时,若返回值为 false,继续执行下一个命令。 *
! 执行 history 列表中的命令。*
10,转义符
有时候,我们想让 通配符,或者元字符 变成普通字符,不需要使用它。那么这里我们就需要用到转义符了。 shell提供转义符有三种。
‘’(单引号) 又叫硬转义,其内部所有的shell 元字符、通配符都会被关掉。注意,硬转义中不允许出现’(单引号)。
“”(双引号) 又叫软转义,其内部只允许出现特定的shell 元字符:$用于参数代换 `用于命令代替
\(反斜杠) 又叫转义,去除其后紧跟的元字符或通配符的特殊意义。