一 第一个shell

    #!/bin/bash
echo "Hello World !"
“#!” 是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行,即使用哪一种Shell。echo命令用于向窗口输出文本。
 
将上面的代码保存为test.sh,并 cd 到相应目录
chmod +x ./test.sh  #使脚本具有执行权限
./test.sh #执行脚本

注意,一定要写成./test.sh,而不是test.sh。运行其它二进制的程序也一样,直接写test.sh,mac/linux系统会去PATH里寻找有没有叫test.sh的。一般来说只有/bin, /sbin, /usr/bin, /usr/sbin等在PATH里,你的当前目录通常不在PATH里,所以写成test.sh是会找不到命令的,要用. /test.sh告诉系统说,就在当前目录找

 
 
 

二 变量

(1)定义变量

定义变量时,变量不加美元符号$,如
var1="shell"
var2=python

注意,变量名和等号之间不能有空格,这可能和你熟悉的所有编程语言都不一样。同时,变量名的命名须遵循如下规则:

  • 首个字符必须为字母(a-z,A-Z)。
  • 中间不能有空格,可以使用下划线(_)。
  • 不能使用标点符号。
  • 不能使用bash里的关键字。

(2)使用变量

使用一个定义过的变量,只需要在变量名之前加美元符号$即可,如

echo $var
echo ${var}

变量名外面的花括号是可选的,加不加都行,加花括号是为了帮助解释器识别变量的边界,比如下面这种情况:

    for skill in Ada Coffe Action Java
do
echo "I am good at ${skill}Script"
done

如果不给skill变量加花括号,写成echo "I am good at $skillScript",解释器就会把$skillScript当成一个变量(其值为空),代码执行结果就不是我们期望的样子了。推荐给所有变量加上花括号,这是个好的编程习惯

(3)只读变量

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

var="java"
readonly var
var="php"

运行脚本会报错提示是只读变量

(4)删除变量

使用 unset 命令可以删除变量.变量被删除后不能再次使用;unset 命令不能删除只读变量

var="java"
unset var
echo $var

上面的脚本没有任何输出

 

(5)特殊变量

特殊变量列表
变量 含义
$0 当前脚本的文件名
$n 传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是$1,第二个参数是$2。
$# 传递给脚本或函数的参数个数。
$* 传递给脚本或函数的所有参数。
$@ 传递给脚本或函数的所有参数。被双引号(" ")包含时,与 $* 稍有不同,下面将会讲到。
$? 上个命令的退出状态,或函数的返回值。
$$ 当前Shell进程ID。对于 Shell 脚本,就是这些脚本所在的进程ID。
 
 
 

四 shell替换

(1)转义字符替换

    #!/bin/bash
a=
echo -e "Value of a is $a \n"

运行结果:

Value of a is 

这里 -e 表示对转义字符进行替换。如果不使用 -e 选项,将会原样输出:

Value of a is \n

下面的转义字符都可以用在 echo 中:

转义字符 含义
\\ 反斜杠
\a 警报,响铃
\b 退格(删除键)
\f 换页(FF),将当前位置移到下页开头
\n 换行
\r 回车
\t 水平制表符(tab键) 
\v 垂直制表符
 
可以使用 echo 命令的 -E 选项禁止转义,默认也是不转义的;使用 -n 选项可以禁止插入换行符。
 

(2)命令替换

命令替换是指Shell可以先执行命令,将输出结果暂时保存,在适当的地方输出。
命令替换的语法:

`command`

注意是反引号,不是单引号,这个键位于 Esc 键下方。

例如,
#!/bin/bash
DATE=`date`
echo "Date is $DATE"

运行结果:Date is 2015年 08月 26日 星期三 17:00:18 CST

 

(3)变量替换

变量替换可以根据变量的状态(是否为空、是否定义等)来改变它的值

可以使用的变量替换形式:

形式 说明
${var} 变量本来的值
${var:-word} 如果变量 var 为空或已被删除(unset),那么返回 word,但不改变 var 的值。
${var:=word} 如果变量 var 为空或已被删除(unset),那么返回 word,并将 var 的值设置为 word。
${var:?message} 如果变量 var 为空或已被删除(unset),那么将消息 message 送到标准错误输出,可以用来检测变量 var 是否可以被正常赋值。
若此替换出现在Shell脚本中,那么脚本将停止运行。
${var:+word} 如果变量 var 被定义,那么返回 word,但不改变 var 的值。
例子如下:
#!/bin/bash

echo ${var:-"Variable is not set"}
echo "1 - Value of var is ${var}" echo ${var:="Variable is not set"}
echo "2 - Value of var is ${var}" unset var
echo ${var:+"This is default value"}
echo "3 - Value of var is $var" var="Prefix"
echo ${var:+"This is default value"}
echo "4 - Value of var is $var" echo ${var:?"Print this message"}
echo "5 - Value of var is ${var}"

运行结果:

 Variable is not set
- Value of var is
Variable is not set
- Value of var is Variable is not set - Value of var is
This is default value
- Value of var is Prefix
Prefix
- Value of var is Prefix

五 运算符

bash支持很多运算符,包括算数运算符、关系运算符、布尔运算符、字符串运算符和文件测试运算符。原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk 和 expr.

expr 最常用, expr 是一款表达式计算工具,使用它能完成表达式的求值操作。

例如两个数相加:

    #!/bin/bash
val=`expr + `
echo "Total value : $val"

运行脚本输出:

Total value : 

两点注意:

  • 表达式和运算符之间要有空格,例如 2+2 是不对的,必须写成 2 + 2,这与我们熟悉的大多数编程语言不一样。
  • 完整的表达式要被 ` ` 包含,注意这个字符不是常用的单引号,在 Esc 键下边。

算术运算符: 加法(+)  减法(-)  乘法(\*)  除法(/)  取余(%)  赋值(=)    相等(==)   不相等(!=)

注意:条件表达式要放在方括号之间,并且要有空格,例如 [$a==$b] 是错误的,必须写成 [ $a == $b ]。

关系运算符:  -eq(相等返回 true)  -ne(不相等返回true)   -gt(左大于右返回true)  -lt(右大于左返回true)   -ge(左大于等于右返回true)   -le(右大于等于左返回true)

布尔运算符:  !(非运算,表达式为true则返回false)  -o(或运算) -a(与运算)

字符串运算符:  =(相等返回true)  !=(不相等返回true)  -z(字符串长度为0返回true)   -n(字符串长度不为0返回true)   [ $str ](字符串不为空返回true)

例子: http://www.runoob.com/linux/linux-shell-basic-operators.html

 
 
 
 

六 字符串

字符串是shell编程中最常用最有用的数据类型(除了数字和字符串,也没啥其它类型好用了),字符串可以用单引号,也可以用双引号,也可以不用引号

(1)单引号

    str='this is a string'
单引号字符串的限制:

  • 单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的;
  • 单引号字串中不能出现单引号(对单引号使用转义符后也不行)。

(2)双引号

    your_name='qinjx'
str="Hello, I know your are \"$your_name\"! \n"

双引号的优点:

  • 双引号里可以有变量
  • 双引号里可以出现转义字符

(3)拼接字符串

    your_name="qinjx"
greeting="hello, "$your_name" !"
greeting_1="hello, ${your_name} !"
echo $greeting $greeting_1

(4)获取字符串长度

    string="abcd"
echo ${#string} #输出

(5)提取子字符串

    string="alibaba is a great company"
echo ${string::} #输出liba
 
 
 

七 数组

bash支持一维数组(不支持多维数组),并且没有限定数组的大小。类似与C语言,数组元素的下标由0开始编号。获取数组中的元素要利用下标,下标可以是整数或算术表达式,其值应大于或等于0

(1)定义数组

在Shell中,用括号来表示数组,数组元素用“空格”符号分割开。定义数组的一般形式为:  array_name=(value1 ... valuen)
    array_name=(value0 value1 value2 value3)

还可以单独定义数组的各个分量:

    array_name[]=value0
array_name[]=value1
array_name[]=value2

可以不使用连续的下标,而且下标的范围没有限制。

(2)读取数组

读取数组元素值的一般格式是: ${array_name[index]},例如

    valuen=${array_name[]}

使用@ 或 * 可以获取数组中的所有元素,例如

    ${array_name[*]}
${array_name[@]}

(3)获取数组的长度

获取数组长度的方法与获取字符串长度的方法相同,例如:

    # 取得数组元素的个数
length=${#array_name[@]}
# 或者
length=${#array_name[*]}
# 取得数组单个元素的长度
lengthn=${#array_name[n]}

八 文件操作

-f file    检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。
-d file    检测文件是否是目录,如果是,则返回 true。
-r file     检测文件是否可读,如果是,则返回 true。
-w file    检测文件是否可写,如果是,则返回 true。
-x file     检测文件是否可执行,如果是,则返回 true。
 
basename解析带路径的文件名称 
var1=/usr/lib/abcdefg.so.bak
var2=/usr/sbin/ifconfiggg
all_name=`basename $var1`
sub_name1=`basename $var1 .bak`
sub_name2=`basename $var2 gg` echo "all_name: $all_name" #all_name: abcdefg.so.bak
echo "sub_name1: $sub_name1" #sub_name1: abcdefg.so
echo "sub_name2: $sub_name2" #sub_name2: ifconfig

九 printf命令

printf 命令用于格式化输出, 是echo命令的增强版。它是C语言printf()库函数的一个有限的变形,并且在语法上有些不同。printf 不像 echo 那样会自动换行,必须显式添加换行符(\n)。

这里仅说明与C语言printf()函数的不同:

  • printf 命令不用加括号
  • format-string 可以没有引号,但最好加上,单引号双引号均可。
  • 参数多于格式控制符(%)时,format-string 可以重用,可以将所有参数都转换。
  • arguments 使用空格分隔,不用逗号。

下面的例子

# format-string为双引号
$ printf "%d %s\n" "abc"
abc
# 单引号与双引号效果一样
$ printf '%d %s\n' "abc"
abc
# 没有引号也可以输出
$ printf %s abcdef
abcdef
# 格式只指定了一个参数,但多出的参数仍然会按照该格式输出,format-string 被重用
$ printf %s abc def
abcdef
$ printf "%s\n" abc def
abc
def
$ printf "%s %s %s\n" a b c d e f g h i j
a b c
d e f
g h i
j
# 如果没有 arguments,那么 %s 用NULL代替,%d 用 代替
$ printf "%s and %d \n"
and
# 如果以 %d 的格式来显示字符串,那么会有警告,提示无效的数字,此时默认置为
$ printf "The first program always prints'%s,%d\n'" Hello Shell
-bash: printf: Shell: invalid number
The first program always prints 'Hello,0'
 

十 if-else

if 语句通过关系运算符判断表达式的真假来决定执行哪个分支。Shell 有三种 if ... else 语句:

(1)if ... fi

    #!/bin/sh
a=
b=
if [ $a == $b ]
then
echo "a is equal to b"
fi
if [ $a != $b ]
then
echo "a is not equal to b"
fi

运行结果: a is not equal to b

(2)if ... else ... fi

    #!/bin/sh
a=
b=
if [ $a == $b ]
then
echo "a is equal to b"
else
echo "a is not equal to b"
fi

运行结果: a is not equal to b

 

(3)if ... elif  ... else ... fi

    #!/bin/sh
a=
b=
if [ $a == $b ]
then
echo "a is equal to b"
elif [ $a -gt $b ]
then
echo "a is greater than b"
elif [ $a -lt $b ]
then
echo "a is less than b"
else
echo "None of the condition met"
fi
运行结果: a is less than b
 

(4)if ... else 语句也经常与 test 命令结合使用

    num1=$[*]
num2=$[+]
if test $[num1] -eq $[num2]
then
echo 'The two numbers are equal!'
else
echo 'The two numbers are not equal!'
fi

运行结果: The two numbers are equal!          test 命令用于检查某个条件是否成立,与方括号[ ]类似。

 
 
 

十一 case esac语句

case ... esac 与其他语言中的 switch ... case 语句类似,是一种多分枝选择结构。case 语句匹配一个值或一个模式,如果匹配成功,执行相匹配的命令.case工作方式如上所示。取值后面必须为关键字 in,每一模式必须以右括号结束。取值可以为变量或常数。匹配发现取值符合某一模式后,其间所有命令开始执行直至 ;;。;; 与其他语言中的 break 类似,意思是跳到整个 case 语句的最后。取值将检测匹配的每一个模式。一旦模式匹配,则执行完匹配模式相应命令后不再继续其他模式。如果无一匹配模式,使用星号 * 捕获该值,再执行后面的命令。
 
下面的脚本提示输入1到4,与每一种模式进行匹配:
    echo 'Input a number between 1 to 4'
echo 'Your number is:\c'
read aNum
case $aNum in
) echo 'You select 1'
;;
) echo 'You select 2'
;;
) echo 'You select 3'
;;
) echo 'You select 4'
;;
*) echo 'You do not select a number between 1 to 4'
;;
esac

输入不同的内容,会有不同的结果,例如:

Input a number between  to
Your number is:
You select

十二 for & while循环

(1)for循环

    for loop in
do
echo "The value is: $loop"
done
运行结果:
The value is:
The value is:
The value is:
The value is:
The value is:
 

(2)while循环

    COUNTER=
while [ $COUNTER -lt ]
do
COUNTER='expr $COUNTER+1'
echo $COUNTER
done
运行结果:

 
 
 

十三  函数

函数可以让我们将一个复杂功能划分成若干模块,让程序结构更加清晰,代码重复利用率更高。像其他编程语言一样,Shell 也支持函数。Shell 函数必须先定义后使用。
Shell 函数的定义格式如下:
function_name () {
list of commands
[ return value ]
}

如果你愿意,也可以在函数名前加上关键字 function.函数返回值,可以显式增加return语句;如果不加,会将最后一条命令运行结果作为返回值。
Shell 函数返回值只能是整数,一般用来表示函数执行成功与否,0表示成功,其他值表示失败。如果 return 其他数据,比如一个字符串,往往会得到错误提示:“numeric argument required”。
如果一定要让函数返回字符串,那么可以先定义一个变量,用来接收函数的计算结果,脚本在需要的时候访问这个变量来获得函数返回值。

看一个例子:
    #!/bin/bash
funWithReturn(){
echo "The function is to get the sum of two numbers..."
echo -n "Input first number: "
read aNum
echo -n "Input another number: "
read anotherNum
echo "The two numbers are $aNum and $anotherNum !"
return $(($aNum+$anotherNum))
}
funWithReturn
# Capture value returnd by last command
ret=$?
echo "The sum of two numbers is $ret !"

运行结果:

The function is to get the sum of two numbers...
Input first number:
Input another number:
The two numbers are and !
The sum of two numbers is !

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

十四 内置其他脚本

. filename

source filename

两种方式的效果相同,简单起见,一般使用点号(.),但是注意点号(.)和文件名中间有一空格。

十五 逐行读入文本

#!/bin/bash
# read line形式1
cat xxx.txt | while read line
do
echo ${line}
done # read line形式2
while read line
do
echo ${line}
done < xxx.txt # awk
cat xxx.txt | awk '{print $0}'
 
 
 

shell 入门教程的更多相关文章

  1. Shell入门教程:Shell变量

    变量 是一种很“弱”的变量,默认情况下,一个变量保存一个串,Shell不关心这个串是什么含义.所以若要进行数学运算,必须使用一些命令例如 let.declare.expr.双括号等. Shell变量可 ...

  2. Shell入门教程:Shell当中的特殊变量

    Shell当中的特殊变量 一.保留变量 $IFS 这个变量中保存了用于分割输入参数的分割字符,默认识空格. $HOME 这个变量中存储了当前用户的根目录路径. $PATH 这个变量中存储了当前 She ...

  3. Shell入门教程:Shell的基本结构

    shell程序的基本组成结构 shell结构大体是由设定变量.内置命令.shell的语法结构.函数组成. 使用实例说明:test.sh #!/bin/bash #说明使用/bin/bash作为这个脚本 ...

  4. Shell入门教程:算术运算

    Bash的算术运算有以下几种方法: 序号 名称 语法 范例 1 算术扩展 $((算术式)) r=$((2+5*8)) 2 使用外部程序 expr 算术式 r=`expr 4 + 5` 3 使用 $[] ...

  5. Shell入门教程:流程控制(1)命令的结束状态

    在Bash Shell中,流程控制命令有2大类:“条件”.“循环”.属于“条件”的有:if.case:属于“循环”的有:for.while.until:命令 select 既属于“条件”,也属于“循环 ...

  6. 【重点】Shell入门教程:流程控制(2)条件判断的写法

    第三节:条件判断的写法 if条件判断中,if的语法结构中的“条件判断”可以有多种形式.测试结果是真是假,就看其传回的值是否为0. 条件测试的写法,有以下10种: 1.执行某个命令的结果 这里的命令,可 ...

  7. 【重点】Shell入门教程:流程控制(3)条件判断式的真假值

    之前曾提到,在Bash中什么是真什么是假,是以命令的结束状态是否为0来做判断.传回0,即为真:传回非0,即为假. 在Bash中,这种可以影响程序流程的式子,称为条件判断式.判断式的操作数分成“单元”及 ...

  8. Shell入门教程:流程控制(6)while 循环

    while循环的语法: while 条件测试 do     命令区域 done 举例: #!/bin/bash declare -i i=1 declare -i sum=0 while ((i< ...

  9. Shell入门教程:Shell函数详解

    Shell函数类似于Shell脚本,里面存放了一系列的指令,不过Shell的函数存在于内存,而不是硬盘文件,所以速度很快,另外,Shell还能对函数进行预处理,所以函数的启动比脚本更快. 1.函数定义 ...

  10. Shell入门教程:Shell函数的返回值

    shell函数返回值一般有3种方式: 1.return语句(默认的返回值) shell函数的返回值可以和其他语言的返回值一样,通过return语句返回. 比如: #!/bin/bash functio ...

随机推荐

  1. HDU 1241Oil Deposits (DFS)

    Problem Description The GeoSurvComp geologic survey company is responsible for detecting underground ...

  2. Vue.js 组件笔记

    Vue 组件总结笔记 一. 创建组件 1. 使用组件三部曲 ( 创建, 注册, 使用 ) 2. 全局组件:Vue.component('tag', {}); 3. 局部组件: components 属 ...

  3. POJ 2773 Happy 2006#素数筛选+容斥原理+二分

    http://poj.org/problem?id=2773 说实话这道题..一点都不Happy好吗 似乎还可以用欧拉函数来解这道题,但正好刚学了容斥原理和二分,就用这个解法吧. 题解:要求输出[1, ...

  4. POJ 1845 Sumdiv#质因数分解+二分

    题目链接:http://poj.org/problem?id=1845 关于质因数分解,模板见:http://www.cnblogs.com/atmacmer/p/5285810.html 二分法思想 ...

  5. hdu_5908_Abelian Period(暴力)

    题目链接:hdu_5908_Abelian Period 题意: 给你n个数字,让你找出所有的k,使得把这n个数字分为k分,并且每份的数字种类和个数必须相同 题解: 枚举k,首先k必须是n的约数,然后 ...

  6. brctl 的使用

    brctl  作用: 用来进行以太网桥接(bridge)的管理 主要用法如下: root@hbg:/# brctl --helpBusyBox v1.22.1 (2016-02-24 11:41:04 ...

  7. Excel教程(10) - 逻辑运算符

    AND 用途:所有参数的逻辑值为真时返回 TRUE(真):只要有 一个参数的逻辑值为假,则返回 FALSE(假). 语法:AND(logical1,logical2,  ). 参数:Logical1, ...

  8. html5+css3学习笔记-prefixfree前缀补全插件

    虽然现代浏览器支持CSS3,但是一些过往的版本或是目前有些CSS3属性的应用还是离不开前缀的.一些牛逼且执着于web技术且乐于分享的仁兄(Lea Verou)就搞了个名叫prefixfree.js的插 ...

  9. sftp配置多用户权限

    sftp配置多用户权限   工作需要,用户上传文件到目录下,用ftp不太安全,选择sftp.让用户在自己的home目录下活动,不能ssh到机器进行操作.   下面开始干活. 查看ssh版本 ssh - ...

  10. 移动前端不得不了解的HTML5 head 头标签(中下篇)

    SEO 优化部分 页面标题<title>标签(head 头部必须)        <title>your title</title>    页面关键词 keywor ...