shell语法

1,配置文件

登陆Linux系统,打开Terminal,使用Shell的时候,系统在背后读取了一大“坨”的配置文件,这些配置文件决定了你的Shell中的变量

  1. /etc/profile:该文件为系统的每个用户设置环境信息,当用户第一次登录系统时,该文件会被执行。 并从/etc/profile.d目录的配置文件中读取shell的设置;
  2. ~/.bash_profile或者~/.bash_login或者~/.profile:系统会依次寻找这三个文件,这些是针对当前用户的配置,但是需要注意的是,这三个文件一般不会同时存在,即使同时存在,系统按照这个顺序找到了一个以后,就不会再去读剩下的了;
  3. ~/.bashrc:该文件包含了专属于当前登录用户的bash shell的bash信息,当登录以及每次打开新的shell时,该文件都会被读取;
  4. /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
 
9,元字符(meta)

= 设定变量。
$ 作变量或运算替换(请不要与 shell prompt 搞混了)。
> 重导向 stdout。 *
< 重导向 stdin。 *
| 命令管线。 *
& 重导向 file descriptor ,或将命令置于背境执行。 *
( ) 将其内的命令置于 nested subshell 执行,或用于运算或命令替换。 *
{ } 将其内的命令置于 non-named function 中执行,或用在变量替换的界定范围。
; 在前一个命令结束时,而忽略其返回值,继续执行下一个命令。 *
&& 在前一个命令结束时,若返回值为 true,继续执行下一个命令。 *
|| 在前一个命令结束时,若返回值为 false,继续执行下一个命令。 *
! 执行 history 列表中的命令。*

 

10,转义符

有时候,我们想让 通配符,或者元字符 变成普通字符,不需要使用它。那么这里我们就需要用到转义符了。 shell提供转义符有三种。
‘’(单引号) 又叫硬转义,其内部所有的shell 元字符、通配符都会被关掉。注意,硬转义中不允许出现’(单引号)。
“”(双引号) 又叫软转义,其内部只允许出现特定的shell 元字符:$用于参数代换 `用于命令代替
\(反斜杠) 又叫转义,去除其后紧跟的元字符或通配符的特殊意义。

 

posted @ 2017-05-21 21:26  soul.stone  阅读(277)  评论(0编辑  收藏  举报