shell学习整理

shell为您提供了对UNIX系统的接口。向你收集的输入,并根据输入执行程序。当一个程序执行完毕后,它会显示该程序的输出。
shell是一个环境,我们可以运行我们的命令,程序和shell脚本。shell有不同的风格,就像有不同风格的操作系统。每个的shell的风格,有它自己的一套识别的命令和功能。

Shell 提示符:



提示符下这就是所谓的命令提示符下$,发出shell。虽然会显示提示,您可以键入一个命令。

shell读取输入后按Enter键。它决定了想要的命令和执行输入的第一个字符。一个字是一个完整的字符集。空格和制表符分隔单词。

以下是一个简单的例子date命令显示当前日期和时间:

$date
Thu Jun 25 08:30:19 MST 2009

你可以定制你的命令提示符下使用环境变量PS1环境教程解释。

Shell 类型:



在UNIX系统下有两种主要类型的shell:

  1. Bourne shell. 如果您使用的是Bourne类型的shell,默认提示符为$字符。

  2. C shell.如果您使用的是C型的shell,默认的提示字符%。

再还有各种Bourne shell的子类别列示如下:

  • Bourne shell ( sh)

  • Korn shell ( ksh)

  • Bourne Again shell ( bash)

  • POSIX shell ( sh)

不同的C型shell如下:

  • C shell ( csh)

  • TENEX/TOPS C shell ( tcsh)

原来的UNIX shell写于20世纪70年代中期,由斯蒂芬·伯恩,在新泽西AT&T贝尔实验室。

Bourne shell 是第一个shell 出现在UNIX系统上,因此,它被称为 "the shell".

Bourne shell的安装通常为 /bin/sh 在大多数UNIX版本。出于这个原因,它是编写脚本使用在几个不同的版本的UNIX shell。

在本教程中,我们将要覆盖大多数基于传播Borne Shell概念。

Shell 脚本:



shell脚本的基本概念是一个命令列表中列出的顺序执行。 #是shell脚本注释前面一英镑符号。

条件测试,如值A大于B值,循环我们去通过大量的数据,读取和存储数据的文件和变量的读取和存储数据,该脚本可能包含的功能。

shell脚本和函数都解释。这意味着他们不会被编译。

我们将在接下来的几个教程写了许多脚本。这将是一个简单的文本文件,在其中,我们会把我们所有的命令和其他一些必要的结构,告诉shell环境做什么,什么时候做。

示例脚本:



假设我们创建了一个test.sh脚本。注意:所有的脚本 .sh扩展。添加任何东西到脚本,需要提醒系统正在启动一个shell脚本。例如:

#!/bin/sh

这是告诉系统Bourne shell的执行下面的命令。这就是所谓的家shebang ,因为“#”符号被称为哈希,和!符号被称为bang。

要创建一个包含这些命令的脚本,把shebang行第一,然后添加命令:

#!/bin/bash
pwd
ls

Shell 注释:



你可以把注释,在你的脚本如下:

#!/bin/bash

# Author : Zara Ali
# Copyright (c) Tutorialspoint.com
# Script follows here:
pwd
ls

现在保存上面的内容,使此脚本可执行如下:

$chmod +x test.sh

现在,你的shell脚本,可随时执行如下:

$./test.sh

This would produce following result:

/home/amrood
index.htm  unix-basic_utilities.htm  unix-directories.htm  
test.sh    unix-communication.htm    unix-environment.htm

注:要执行任何程序在当前目录中,执行可使用 ./program_name

扩展Shell脚本:



Shell脚本有几个必要的结构告诉shell环境做什么,什么时候做。当然,大多数脚本是比上述更加复杂。

shell毕竟,真正的编程语言,完成变量,控制结构,等等。无论脚本变得多么复杂,但是,它仍然是顺序执行的命令的列表。

下面的脚本使用读命令从键盘输入,并将其分配给变量PERSON的值,并最终打印在stdout。

#!/bin/sh

# Author : Zara Ali
# Copyright (c) Tutorialspoint.com
# Script follows here:

echo "What is your name?"
read PERSON
echo "Hello, $PERSON"

下面是运行的脚本示例:

$./test.sh
What is your name?
xf
Hello, xf
$

Shell 使用Shell变量

变量是一个字符串,我们分配一个值。分配的值可以是一个数字,文本,文件名,设备,或任何其他类型的数据。

变量是没有超过实际数据的指针。 shell,可以创建,分配和删除变量。

变量名:



变量的名称可以包含只有字母(a到z或A到Z),数字(0〜9)或下划线(_)。

按照惯例,UNIX的shell变量将有自己的名称以大写字母。

下面的例子是有效的变量名:

_ALI
TOKEN_A
VAR_1
VAR_2

以下是无效的变量名的例子:

2_VAR
-VARIABLE
VAR1-VAR2
VAR_A!

不能使用其他字符,如!,*或 - 这些字符有特殊含义。

定义变量:



变量定义如下:

variable_name=variable_value

例如:

NAME="xf"

上面的例子中定义的变量名和分配值“Zara Ali”。这种类型的变量被称为标量变量。一个标量变量只能容纳一个值一次。

shell可以存储任何你想在一个变量的值。例如:

VAR1="xf"
VAR2=100

访问值:



为了访问存储在一个变量的值,它的名字的前缀为美元符号($):

例如,下面的脚本将访问的价值定义的变量名,将它打印在标准输出:

#!/bin/sh

NAME="xf"
echo $NAME

这将产生以下值:

xf

只读变量:



shell提供了一种标记为只读变量使用的只读命令。后一个变量被标记为只读的,它的值不能被改变。

例如,下面的脚本将给出错误提示,同时试图改变NAME的值: 

#!/bin/sh

NAME="xf xy"
readonly NAME
NAME="yyxf"

这个结果将产生以下如下:

/bin/sh: NAME: This variable is read only.

取消设置变量:



注销或删除的变量告诉shell删除的变量的变量列表做了跟踪。一旦您取消设置变量,你不可以访问存储在变量值。

以下是使用unset命令定义一个变量的语法:

unset variable_name

上面的命令将取消设置定义的变量值。下面是一个简单的例子:

#!/bin/sh

NAME="xf"
unset NAME
echo $NAME

上面的例子会不会打印出任何东西。不能使用unset命令取消定义的变量没有被标记为只读。

变量类型:



当一个shell运行,存在三种主要类型的变量:

  • 局部变量: 局部变量是一个变量所做的是在当前实例中的shell。这不是程序由shell开始。在命令提示符下设置。

  • 环境变量: 环境变量是一个变量所做的是任何子进程的shell。有些程序需要以正常的环境变量。通常一个shell脚本定义,只有那些环境变量所需要的程序没有运行。

  • Shell 变量: shell变量是一个特殊的变量,由shell设置,也是shell正常需要。一些合成变量环境变量,而其他局部变量。


Shell 特殊变量


以前的教程中说过有关在变量名中使用某些非字母数字字符。这是因为这些字符中使用特殊的Unix变量的名称。这些变量被保留用于特定功能。

例如,$字符表示进程ID号,或PID,在当前shell:

$echo $$

上面的命令将写入在当前shell的PID:

29949

以下下表显示了一些特殊的变量,你可以在你的shell脚本中使用:

变量 描述
$0 The filename of the current script. //当前脚本的文件名
$n These variables correspond to the arguments with which a script was invoked. Here n is a positive decimal number corresponding to the position of an argument (the first argument is $1, the second argument is $2, and so on).//这些变量对应的实参,脚本被调用。这里n是一个正的十进制数对应的实参的位置第一个参数是$1第二个参数是$2等等
$# The number of arguments supplied to a script.//脚本提供的参数数目
$* All the arguments are double quoted. If a script receives two arguments, $* is equivalent to $1 $2.//所有的参数都是双引号。如果脚本需要两个参数$ *相当于$1 $2
$@ All the arguments are individually double quoted. If a script receives two arguments, $@ is equivalent to $1 $2.//所有的参数都是单独的双引号。如果脚本需要两个参数$相当于$1 $2
$? The exit status of the last command executed.//最后一个命令的退出状态
$$ The process number of the current shell. For shell scripts, this is the process ID under which they are executing.//当前的壳的进程数。shell脚本这是它们执行的进程ID
$! The process number of the last background command.//最后的背景过程的命令数

命令行参数:



该命令行参数 $1, $2, $3,...$9 是位置参数,与0美元指向实际的命令,程序,shell脚本,函数和 $1, $2, $3,...$9 作为参数的命令。

下面的脚本使用命令行相关的各种特殊变量:

#!/bin/sh

echo "File Name: $0"
echo "First Parameter : $1"
echo "First Parameter : $2"
echo "Quoted Values: $@"
echo "Quoted Values: $*"
echo "Total Number of Parameters : $#"

下面是一个示例运行上面的脚本:

$./test.sh xf yy
File Name : ./test.sh
First Parameter : xf
Second Parameter : yy
Quoted Values: xf yy
Quoted Values: xf yy
Total Number of Parameters : 2

特殊参数$ *和$ @:



有特殊的参数,允许在一次访问所有的命令行参数。 $ *和$ @都将相同的行动,除非它们被括在双引号“”。

这两个参数指定的命令行参数,但“$ *”特殊参数需要整个列表作为一个参数之间用空格和“$ @”特殊参数需要整个列表,将其分为不同的参数。

我们可以写下面所示的命令行参数处理数目不详的$ *$ @特殊参数的shell脚本:

#!/bin/sh

for TOKEN in $*
do
   echo $TOKEN
done

有一个例子运行上面的脚本:

$./test.sh xf yy 10 Years Old
xf
yy
10
Years
Old

注:在这里 do...done是一种循环,在以后的教程中,我们将涵盖。

退出状态:

 


$? 变量表示前一个命令的退出状态。

退出状态是一个数值,完成后返回的每一个命令。作为一项规则,大多数命令返回,如果他们不成功退出状态为0,如果他们是成功的。

一些命令返回其他特殊退出状态。例如,一些命令区分类型的错误,并且将返回各种退出值取决于特定类型失效。

成功的命令如下面的例子:

$./test.sh xf yy
File Name : ./test.sh
First Parameter : xf
Second Parameter : yy
Quoted Values: xf yy
Quoted Values: xf yy
Total Number of Parameters : 2
$echo $?
0
$


Shell 数组/Arrays


shell变量是有足够的能力保持一个单一的值。这种类型的变量被称为标量变量。

Shell支持不同类型的变量称为数组变量,可以在同一时间容纳多个值。阵列,提供了一组变量进行分组的方法的。而不是创建一个新的名称为每个变量所需要的,你可以使用一个单一的阵列存储所有其他变量的变量。

所有讨论shell变量的命名规则将适用数组命名。

定义数组值:



一个数组变量和标量变量之间的差异可以解释如下。

说,你正试图表示各种学生为变量集的名字。每一个单个变量是一个标量变量,如下所示:

NAME01="zxl"
NAME02="xf"
NAME03="lfs"
NAME04="yy"
NAME05="zyx"

我们可以用一个单一的阵列来存储所有上述提及的名称。以下是最简单的方法创建一个数组变量分配一个值,其索引之一。这是表示,如下所示:

array_name[index]=value   

如:array_name[5]=NAME

array_name 是数组名,索引是在阵列中,你要设置的项目索引,值是你想要的值设置该项目。 

作为一个例子,下面的命令:

NAME[0]="zxl"

NAME[1]="xf"

NAME[2]="lfs"

NAME[3]="yy"

NAME[4]="zyx"

如果您使用的是ksh shell在这里初始化数组的语法:

set -A array_name value1 value2 ... valuen

如果您使用的是bash shell中,这里是初始化数组的语法:

array_name=(value1 ... valuen)

如:array_name=(NAME[0] NAME[1] NAME[2] NAME[3] NAME[4] valuen)

访问数组值:



当您设置任何数组变量,并可访问它,如下所示:

${array_name[index]}

在这里,array_name是数组名称,index是索引进行访问的值。下面是一个简单的例子:

#!/bin/sh

NAME[0]="zxl"
NAME[1]="xf"
NAME[2]="lfs"
NAME[3]="yy"
NAME[4]="zyx"
echo "First Index: ${NAME[0]}"
echo "Second Index: ${NAME[1]}"

This would produce following result:

$./test.sh
First Index: zxl
Second Index: xf

您可以访问数组中的所有项目通过以下方式之一:

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

 array_name 是数组的名字你所感兴趣的 以下是个最简单的例子:

#!/bin/sh

<span style="font-family:Courier New;">NAME[0]="zxl"
NAME[1]="xf"
NAME[2]="lfs"
NAME[3]="yy"
NAME[4]="zyx"
NAME[5]="zsm"
echo "First Method: ${NAME[*]}"
echo "Second Method: ${NAME[@]}"</span>

这将产生以下结果:

$./test.sh
First Method: zxl xf lfs yy zyx zsm
Second Method: zxl xf lfs yy zyx zsm

Shell 基本运算符

有各种不同的运算符shell都支持。本教程是基于默认shell(Bourne),所以我们要涵盖所有重要的Bourne Shell运算符。

有以下的运算符,我们将要讨论的:

  • 算术运算符。

  • 关系运算符。

  • 布尔运算符。

  • 字符串运算符。

  • 文件测试操作。

Bourne shell的最初并没有任何机制来执行简单的算术,但它使用外部程序,无论是awk或必须简单的程序expr。

下面是简单的例子,把两个数相加:

#!/bin/sh

val=`expr 2 + 2`
echo "Total value : $val"

这将产生以下结果:

Total value : 4

记下有以下几点:

  • 运算符和表达式之间必须有空格,例如2+2是不正确的,因为它应该写成2 + 2。

  • ``,称为倒逗号之间应包含完整的表达。

算术运算符:



算术运算符有以下Bourne Shell支持。

假设变量a=10,变量b=20:

算术运算符例子

运算符 描述 例子
+ Addition - Adds values on either side of the operator `expr $a + $b` will give 30
- Subtraction - Subtracts right hand operand from left hand operand `expr $a - $b` will give -10
* Multiplication - Multiplies values on either side of the operator `expr $a \* $b` will give 200
/ Division - Divides left hand operand by right hand operand `expr $b / $a` will give 2
% Modulus - Divides left hand operand by right hand operand and returns remainder `expr $b % $a` will give 0
= Assignment - Assign right operand in left operand a=$b would assign value of b into a
== Equality - Compares two numbers, if both are same then returns true. [ $a == $b ] would return false.
!= Not Equality - Compares two numbers, if both are different then returns true. [ $a != $b ] would return true.

这是非常重要的,这里要注意,所有的条件式将放在方括号内,他们身边有一个空格,例如 [ $a == $b ]是正确的,为[$a==$b] 是不正确的。

所有的算术计算,使用长整数。

<pre name="code" class="cpp">a=10
b=20

echo $a
echo $b
array_name[5]=val
val[0]=`expr $a + $b`
val[1]=`expr $a - $b`
val[2]=`expr $a \* $b`
val[3]=`expr $b / $a`
val[4]=`expr $b % $a`
echo "Total value : ${val[*]}"

echo a=$b

if [ $a == $b ]; then
    echo "a is equal to b"
else
    echo "a is not equal to b"
fi
 
 

关系运算符:

Bourne Shell的支持,关系运算符的具体数值。这些运算符不能使用字符串值,除非它们的值是数字。

例如,运算符将努力检查10和20之间的关系,以及在“10”和“20”,但不是“10”和“21”之间。

假设变量a=10,变量b=20:

关系运算符

运算符 描述 示例
-eq Checks if the value of two operands are equal or not, if yes then condition becomes true.//检查,如果两个操作数的值相等如果是的话,情况变得真实 [ $a -eq $b ] is not true.
-ne Checks if the value of two operands are equal or not, if values are not equal then condition becomes true.//检查,如果两个操作数的值相等如果值不相等的条件为真 [ $a -ne $b ] is true.
-gt Checks if the value of left operand is greater than the value of right operand, if yes then condition becomes true.//检查操作数的值大于操作数的值如果是的话,情况变得真实 [ $a -gt $b ] is not true.
-lt Checks if the value of left operand is less than the value of right operand, if yes then condition becomes true.//检查操作数的值小于操作数的值如果是的话,情况变得真实 [ $a -lt $b ] is true.
-ge Checks if the value of left operand is greater than or equal to the value of right operand, if yes then condition becomes true.//检查操作数的值大于或等于操作数的值如果是的话,情况变得真实 [ $a -ge $b ] is not true.
-le Checks if the value of left operand is less than or equal to the value of right operand, if yes then condition becomes true.//检查操作数的值小于或等于操作数的值如果是的话,情况变得真实 [ $a -le $b ] is true.

这里要注意,所有的条件式将放在方括号内,他们周围有一个空格,这是非常重要的,例如 [ $a <= $b ]是正确的, [$a <= $b]是不正确的。

布尔运算:

布尔运算符有以下Bourne Shell的支持。

假设变量一个变量b=10,然后变量b=20:

布尔运算示例

运算符 描述 示例
! This is logical negation. This inverts a true condition into false and vice versa.//这是合乎逻辑的否定。真正的条件反之亦然 [ ! false ] is true.
-o This is logical OR. If one of the operands is true then condition would be true.//这是逻辑或。如果一个操作数是真的话,情况会是真的 [ $a -lt 20 -o $b -gt 100 ] is true.
-a This is logical AND. If both the operands are true then condition would be true otherwise it would be false.//这是逻辑并且。如果两个操作数都是真的那么情况会是真的那么虚假 [ $a -lt 20 -a $b -gt 100 ] is false.

字符串运算符:

有下列字符串运算由Bourne Shell支持。

假设变量a=“abc”和变量b=“efg”:

关系运算例子

运算符 描述 例子
= Checks if the value of two operands are equal or not, if yes then condition becomes true.//检查,如果两个操作数的值相等如果是的话,情况变得真实 [ $a = $b ] is not true.
!= Checks if the value of two operands are equal or not, if values are not equal then condition becomes true.//检查,如果两个操作数的值相等如果值不相等的条件为真 [ $a != $b ] is true.
-z Checks if the given string operand size is zero. If it is zero length then it returns true.//检查,如果给定字符串操作数大小是零。如果是零长度返回true [ -z $a ] is not true.
-n Checks if the given string operand size is non-zero. If it is non-zero length then it returns true.//检查,如果给定字符串操作数大小是零。如果是非零的长度,则返回 [ -n $a ] is not false.
str Check if str is not the empty string. If it is empty then it returns false.//如果不是空字符串str。如果为空,则返回false [ $a ] is not false.

文件测试操作:

有以下是操作测试Unix文件相关联的各种属性。

假设一个的变量文件保存现有文件名“test”,其大小为100字节,有读,写和执行权限:

文件测试操作例子

操作符 描述 示例
-b file Checks if file is a block special file if yes then condition becomes true.//检查文件是否是一块特殊文件如果是那么的条件下成为真正的 [ -b $file ] is false.
-c file Checks if file is a character special file if yes then condition becomes true.//检查,如果文件是一个字符特殊文件如果是那么的条件下成为真正的 [ -b $file ] is false.
-d file Check if file is a directory if yes then condition becomes true.//检查文件是否是一个目录,如果是的话,情况变得真实 [ -d $file ] is not true.
-f file Check if file is an ordinary file as opposed to a directory or special file if yes then condition becomes true.//检查文件是否是一个普通的文件目录或特殊文件如果是那么的条件下成为真正的 [ -f $file ] is true.
-g file Checks if file has its set group ID (SGID) bit set if yes then condition becomes true.//检查文件IDSGID位设置,如果是的话,情况变得真实 [ -g $file ] is false.
-k file Checks if file has its sticky bit set if yes then condition becomes true.//检查是否集的文件如果是那么的条件下成为真正的 [ -k $file ] is false.
-p file Checks if file is a named pipe if yes then condition becomes true.//检查,如果文件是一个命名管道,如果是的话,情况变得真实 [ -p $file ] is false.
-t file Checks if file descriptor is open and associated with a terminal if yes then condition becomes true.//检查,如果文件描述符是开放的,如果是的话,情况变得真实与终端相关联的 [ -t $file ] is false.
-u file Checks if file has its set user id (SUID) bit set if yes then condition becomes true.//检查文件设置用户ID如果是的那么suid位设置条件为真 [ -u $file ] is false.
-r file Checks if file is readable if yes then condition becomes true.//检查如果那么的条件下成为真正的文件是可读的 [ -r $file ] is true.
-w file Check if file is writable if yes then condition becomes true.//检查文件是否是可写的如果是那么的条件下成为真正的 [ -w $file ] is true.
-x file Check if file is execute if yes then condition becomes true.//检查文件是否执行如果是那么的条件下成为真正的 [ -x $file ] is true.
-s file Check if file has size greater than 0 if yes then condition becomes true.//检查文件大小大于0,如果是的话,情况变得真实 [ -s $file ] is true.
-e file Check if file exists. Is true even if file is a directory but exists.//检查,如果文件存在。真的,即使文件目录存在的目的 [ -e $file ] is true.

C Shell 操作符:

以下链接将在C Shell运算符给出简单的用法。

C Shell 运算符

Korn Shell 运算符:

以下链接将在Korn  Shell运算符给出简单的用法

Korn Shell 运算符

Shell 条件语句

在编写shell脚本,有可能是一种情况,当你需要采取一个路径两条路径。所以,需要利用条件语句,让程序作出正确的决策和执行正确的动作。

UNIX Shell支持条件语句,从而根据不同的条件下执行不同的操作。在这里,我们将解释以下两个决策语句:

  • if...else 语句

  • case...esac 条件语句

if...else 语句:

if else语句是有用的决策语句,可以用来从一个给定的选项中选择一个选项。

UNIX Shell支持以下形式的if.. else语句:

大部分的 if 语句检查前面的章节中讨论的关系运算符的关系。

case...esac 语句:

if...elif 可以使用多个 elif  语句执行多分支。然而,这并不总是最佳的解决方案,尤其是当所有的分支依赖于一个单一的变量的值。

UNIX Shell支持  case...esac 语句处理正是由于这个情况,它这样做更有效地比 if... elif 语句。

目前只有一种形式的情况下,这里详细case...esac 语句:

UNIX shell 的 case...esac 语句,比较像其他编程语言里的 switch...case ,如C或C + +和Perl等非常相似。

Shell 循环类型

循环是一个强大的编程工具,使您能够重复执行一组命令。在本教程中,您将学习以下类型的循环Shell程序:

你会根据不同情况使用不同的循环。例如用 while 循环执行命令,直到给定的条件下是 ture ,循环直到执行到一个给定的条件为 false。

有良好的编程习惯,将开始使用情况的基础上适当的循环。这里while和for循环类似在大多数其他的编程语言,如C,C++ 和 Perl 等。

嵌套循环:

所有支持嵌套循环的概念,这意味着可以把一个循环内其他类似或不同的循环。这种嵌套可以去高达无限数量的时间根据需要。

嵌套的while循环和类似的方式,可以嵌套其他循环的基础上的编程要求下面是一个例子:

嵌套while循环:

作为另一个while循环的身体的一部分,这是可以使用一个while循环。

语法:

                           
while command1 ; # this is loop1, the outer loop 
do
 
   Statement(s) to be executed if command1 is true

   while command2 ; # this is loop2, the inner loop
   do
      Statement(s) to be executed if command2 is true
   done

   Statement(s) to be executed if command1 is true
done

例如:



这里是循环嵌套一个简单的例子,让我们添加另一个倒计时循环内的循环,数到九:

#!/bin/sh

a=0
while [ "$a" -lt 10 ]    # this is loop1
do
   b="$a"
   while [ "$b" -ge 0 ]  # this is loop2
   do
      echo -n "$b "
      b=`expr $b - 1`
   done
   echo
   a=`expr $a + 1`
done

这将产生以下结果。重要的是要注意 echo -n 是如何工作。在这里,-n选项echo ,以避免打印一个新行字符。

0
1 0
2 1 0
3 2 1 0
4 3 2 1 0
5 4 3 2 1 0
6 5 4 3 2 1 0
7 6 5 4 3 2 1 0
8 7 6 5 4 3 2 1 0
9 8 7 6 5 4 3 2 1 0

Shell 循环控制break/continue


到目前为止,我们已经看到了,创建循环和使用循环来完成不同的任务。有时候,你需要停止循环或跳过循环迭代。

在本教程中,您将了解以下两个语句用于控制 Shell 循环:

  1. break 语句

  2. continue 语句

无限循环:



循环有限的生命,他们跳出来,一旦条件是 false 还是 false 取决于循环。

由于所需的条件是不符合一个循环可能永远持续下去。永远不会终止执行一个循环执行无限次数。出于这个原因,这样的循环被称为无限循环。

例子:



下面是一个简单的例子,使用while循环显示数字0到9:

#!/bin/sh

a=10

while [ $a -lt 10 ]
do
   echo $a
   a=`expr $a + 1`
done

这个循环将永远持续下去,因为常是大于10,它永远不会成为小于10。所以这是无限循环真实的例子。

break语句:



break语句用于终止整个循环的执行,完成后所有行代码break语句的执行。然后,它逐级的代码跟在循环结束。

语法



将用于以下break语句退出循环:

break

将用于以下break语句退出循环:

break n

这里n指定的第n个封闭的循环退出。

例子:



下面是一个简单的例子展示了循环将终止只要一变为5:

#!/bin/sh

a=0

while [ $a -lt 10 ]
do
   echo $a
   if [ $a -eq 5 ]
   then
      break
   fi
   a=`expr $a + 1`
done

这将产生以下结果:

0
1
2
3
4
5

下面是一个简单的嵌套循环的例子。这个脚本打破两个循环,如果的 var1 等于2 和 var2 等于0:

#!/bin/sh

for var1 in 1 2 3
do
   for var2 in 0 5
   do
      if [ $var1 -eq 2 -a $var2 -eq 0 ]
      then
         break 2
      else
         echo "$var1 $var2"
      fi
   done
done

这将产生以下结果。内循环有一个 break 命令与参数2。这表明,如果条件得到满足应该跳出外循环,并最终从内循环跳出。

1 0
1 5

continue 语句:



continue语句break命令类似,但它会导致当前迭代的循环退出,而不是整个循环。

这种参数是有用的,当一个错误已经发生,但你想尝试执行下一个循环迭代。

语法

continue


和break语句一样,一个整数参数可以给continue命令跳过嵌套循环的命令。

continue n

这里n指定第n个封闭循环 continue 。

例子:



下面的循环利用continue语句返回,并开始处理下一个语句:

#!/bin/sh

NUMS="1 2 3 4 5 6 7"

for NUM in $NUMS
do
   Q=`expr $NUM % 2`
   if [ $Q -eq 0 ]
   then
      echo "Number is an even number!!"
      continue
   fi
   echo "Found odd number"
done

这将产生以下结果:

Found odd number
Number is an even number!!
Found odd number
Number is an even number!!
Found odd number
Number is an even number!!
Found odd number


Shell 替代


替代是什么?



Shell当它遇到一个表达式,其中包含一个或多个特殊字符进行替代。

例子:



下面的例子,同时使打印取代的其值的变量的值。同时“\n”是一个新行取代:

#!/bin/sh

a=10
echo -e "Value of a is $a \n"

这将产生下面的结果。这里-e选项可以解释反斜杠转义。

Value of a is 10

下面是结果没有-e选项:

Value of a is 10\n

这里echo命令可以用在以下转义序列:

转义 描述
\\ backslash //反斜杠
\a alert (BEL) //警报
\b backspace //退格键
\c suppress trailing newline  //取消尾随换行
\f form feed  //换页
\n new line
\r carriage return //回车
\t horizontal tab //水平制表符
\v vertical tab //垂直制表符

可以使用-E选项禁用解释反斜杠转义(默认)。

您可以使用-n选项来禁用插入新行。

命令替换:



命令替换shell执行的机制,一组给定的命令,然后替代它们的输出在命令。

语法



执行命令替换的命令时,被给定为:

`command`

当执行命令替换,确保您使用的是反引号,不是单引号字符。

例子:



命令替换一般是用一个命令的输出分配给一个变量。下面的例子演示命令替换:

#!/bin/sh

DATE=`date`
echo "Date is $DATE"

USERS=`who | wc -l`
echo "Logged in user are $USERS"

UP=`date ; uptime`
echo "Uptime is $UP"

这将产生以下结果:

Date is Thu Jul  2 03:59:57 MST 2009
Logged in user are 1
Uptime is Thu Jul  2 03:59:57 MST 2009
03:59:57 up 20 days, 14:03,  1 user,  load avg: 0.13, 0.07, 0.15

变量替代:



变量替换可使Shell程序员操纵变量的值,根据其状态。

这里是所有可能的替换如下表:

格式 描述
${var} Substitue the value of var.//VaR
${var:-word} If var is null or unset, word is substituted for var. The value of var does not change.//如果变量是空的取消取代的Word的VAR VAR没有变化。
${var:=word} If var is null or unset, var is set to the value of word.//如果变量是无效的或不VAR将设置word的值
${var:?message} If var is null or unset, message is printed to standard error. This checks that variables are set correctly.//如果变量是无效的或不,信息打印到标准错误。这个检查变量设置正确
${var:+word} If var is set, word is substituted for var. The value of var does not change.//如果变量设置,word代替var. VaR值没有变化

例子:



下面的例子显示各种状态,上述替代:

#!/bin/sh

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
1 - Value of var is
Variable is not set
2 - Value of var is Variable is not set

3 - Value of var is
This is default value
4 - Value of var is Prefix
Prefix
5 - Value of var is Prefix


Shell 引用机制


元字符:



UNIX Shell提供各种元字符有特殊的意义,同时利用他们在任何Shell脚本,并导致终止一个字,除非引用。

举个例子: ?匹配一个单一的系统字符,而列出文件中的目录和*匹配多个字符。下面是一个清单shell特殊字符(也称为元字符):

* ? [ ] ' " \ $ ; & ( ) | ^ < > new-line space tab

它与前可能被引用的字符(例如,放置自身) \.

例子:



下面的例子,显示了如何打印  a * 或 a ?:

#!/bin/sh

echo Hello; Word

这将产生下面的结果。

Hello
./test.sh: line 2: Word: command not found

shell returned 127

现在,让我们尝试使用带引号的字符:

#!/bin/sh

echo Hello\; Word

这将产生以下结果:

Hello; Word

$符号是一个元字符,所以它必须被引用,以避免特殊处理:

#!/bin/sh

echo "I have \$1200"

这将产生以下结果:

I have $1200

是以下四种形式引用:

引用 描述
Single quote
//
单引号
All special characters between these quotes lose their special meaning.//在这些引用所有的特殊字符失去他们的特殊意义
Double quote
//
双引号
Most special characters between these quotes lose their special meaning with these exceptions://最特殊的字符之间的这些名言失去他们的特殊意义与这些例外
  • $
  • `
  • \$
  • \'
  • \"
  • \\
Backslash
//反斜杠
Any character immediately following the backslash loses its special meaning.//任何字符后立即反斜杠失去它的特殊含义
Back Quote
//返回引用
Anything in between back quotes would be treated as a command and would be executed.//任何之间回来的报价将被视为一个命令被执行

单引号:



考虑echo命令,其中包含许多特殊的shell字符:

echo <-$1500.**>; (update?) [y|n]

将在每个特殊字符前的反斜杠是繁琐的,使该行难以阅读:

echo \<-\$1500.\*\*\>\; \(update\?\) \[y\|n\]

有一个简单的方法来引用一大组字符。将一个单引号(')的开头和结尾的字符串:

echo '<-$1500.**>; (update?) [y|n]'

单引号内的任何字符均以一个反斜杠,就好像是在前面的每个字符。所以,现在这个echo命令将显示正确。

如果要输出一个字符串内出现一个单引号,你不应该把单引号内的整个字符串,而不是对子进行使用反斜杠(\)如下:

echo 'It\'s Shell Programming'

echo "It's Shell Programming"

双引号:



尝试执行以下shell脚本。这个shell脚本使用单引号:


VAR=ZARA
echo '$VAR owes <-$1500.**>; [ as of (`date +%m/%d`) ]'

这将产生以下输出结果:

$VAR owes <-$1500.**>; [ as of (`date +%m/%d`) ]

所以这不是你想显示什么。很明显,单引号防止变量替换。如果想替换的变量值和倒置逗号如预期那样运作,那么就需要在双引号命令如下:

VAR=ZARA
echo "$VAR owes <-\$1500.**>; [ as of (`date +%m/%d`) ]"

这将产生以下结果:

ZARA owes <-$1500.**>; [ as of (04/23) ]

双引号带走下列以外的所有字符的特殊含义:

  • $ 参数替代。

  • 用于命令替换的反引号。

  • \$ 使字面美元标志。

  • \` 使文字反引号。

  • \" 启用嵌入式双引号。

  • \\ 启用嵌入式反斜杠。

  • 所有其他\字符是文字(而不是指定)。

单引号内的任何字符均以一个反斜杠,就好像是在前面的每个字符。所以,现在这个echo命令将显示正确。

如果要输出一个字符串内出现一个单引号,不应该把单引号内的整个字符串,而不是对子进行使用反斜杠(\)如下:

echo 'It\'s Shell Programming'

反引号:



把反引号之间的任何shell命令将执行命令

语法



下面是一个简单的语法,把反引号之间的任何Shell命令:

例子:

var=`command`

例子:



继执行date命令,产生的结果将被存储在 DATA 变量。

DATE=`date`

echo "Current Date: $DATE"

这将产生以下输出结果:

Current Date: Thu Jul  2 05:28:45 MST 2009


Shell 输入/输出重定向


大多数 Unix 系统命令从终端的输入和发送所产生的输出返回​​到您的终端。一个命令通常从一个地方叫标准输入,默认情况下,这恰好是你的终端读取输入。同样,一个命令通常写入其输出到标准输出,这也是默认情况下,从你的终端。

输出重定向:



通常用于标准输出命令的输出可以很容易地转移到一个文件中代替。这种能力被称为输出重定向:

如果记号> file附加任何命令,通常写入其输出到标准输出,该命令的输出将被写入文件,而不是你的终端:

检查使用 who 命令,将完整的输出重定向命令在用户文件。

$ who > users

请注意,没有输出出现在终端中。这是因为输出已被重定向到指定的文件从默认的标准输出设备(终端)。如果想检查用户的文件,然后将完整的内容:

$ cat users
oko         tty01   Sep 12 07:30
ai          tty15   Sep 12 13:32
ruth        tty21   Sep 12 10:10
pat         tty24   Sep 12 13:07
steve       tty25   Sep 12 13:03
$

如果命令输出重定向到一个文件,该文件已经包含了一些数据,这些数据将会丢失。考虑这个例子:

$ echo line 1 > users
$ cat users
line 1
$

您可以使用>>运算符将输出附加在现有的文件如下:

$ echo line 2 >> users
$ cat users
line 1
line 2
$

输入重定向:



正如一个命令的输出可以被重定向到一个文件中,所以可以输入一个命令从文件重定向。作为不是字符>用于输出重定向,小于字符<用于重定向一个命令的输入。

通常需要的命令,他们从标准输入的输入可以有自己的这种方式从文件输入重定向。例如,上面生成的文件中的用户的数量来计算的行,可以执行如下命令:

$ wc -l users
2 users
$

在这里,它产生的输出2行。可以指望的文件中的行数 wc 命令的标准输入重定向用户从文件:

$ wc -l < users
2
$

请注意,在由两种形式的wc命令产生的输出是有区别的。在第一种情况下,该文件的用户的名称列出的行数,在第二种情况下,它不是。

在第一种情况下,wc 知道,它是用户从文件读取输入。在第二种情况下,只知道它是从标准输入读取输入,所以它不显示文件名。

Here 文档:



 here document 是用来输入重定向到一个交互式shell脚本或程序。

在一个shell脚本中,我们可以运行一个交互式程序,无需用户操作,通过提供互动程序或交互式shell脚本所需的输入。

这里的文件的一般形式是:

command << delimiter
document
delimiter

这里的 shell 解释<<操作指令读取输入,直到它找到含有指定分隔符线。所有输入行的行分隔符,然后送入标准输入的命令。

分界符告诉shell 这里文件已完成。没有它,shell 不断的读取输入。分隔符必须是一个字不包含空格或制表符。

以下是输入命令wc -1 进行计数的行的总数:

$wc -l << EOF
	This is a simple lookup program 
	for good (and bad) restaurants
	in Cape Town.
EOF
3
$

可以在here document 打印多行,使用你的脚本如下:

#!/bin/sh

cat << EOF
This is a simple lookup program 
for good (and bad) restaurants
in Cape Town.
EOF	

这将产生以下结果:

This is a simple lookup program
for good (and bad) restaurants
in Cape Town.

下面的脚本运行一个会话vi文本编辑器中的输入和保存文件test.txt。

#!/bin/sh

filename=test.txt
vi $filename <<EndOfCommands
i
This file was created automatically from
a shell script
^[
ZZ
EndOfCommands

如果运行这个脚本,用vim作为vi,那么很可能会看到类似以下的输出:

$ sh test.sh
Vim: Warning: Input is not from a terminal
$

运行该脚本后,你应该看到以下内容添加到文件test.txt:

$ cat test.txt
This file was created automatically from
a shell script
$

丢弃输出:



有时会需要执行命令,但不想显示在屏幕上的输出。在这种情况下,可以丢弃的输出重定向到文件 /dev/null:

$ command > /dev/null

这里 command 是要执行的命令的名字。文件/dev/null 是一个特殊的文件自动放弃其所有的输入。

同时要放弃一个命令的输出和错误输出,使用标准的重定向到STDOUT 到 STDERR重定向:

$ command > /dev/null 2>&1

在这里,2代表stderr和1代表STDOUT。可以上显示一条消息到STDERR 到 STDERR重定向标准输入到如下:

$ echo message 1>&2

重定向命令:



以下是命令,可以使用重定向的完整列表:

命令 描述
pgm > file Output of pgm is redirected to file//输出重定向到文件PGM
pgm < file Program pgm reads its input from file.//程序读取输入文件PGM
pgm >> file Output of pgm is appended to file.//输出PGM追加到文件
n > file Output from stream with descriptor n redirected to file.//广义n重定向到文件流输出
n >> file Output from stream with descriptor n appended to file.//广义N追加到文件流输出
n >& m Merge output from stream n with stream m.//合并M N流输出
n <& m Merge input from stream n with stream m.//合并M N流输入
<< tag Standard input comes from here through next tag at start of line.//标准输入来自这里通过标签在开始线
| Takes output from one program, or process, and sends it to another.//输出从一个程序或过程并将其发送到另一个

需要注意的是文件描述符0是正常标准输入(STDIN),1是标准输出(STDOUT),标准错误输出(STDERR)。



Shell 函数


函数允许您对分解成更小的,逻辑子部分,然后可以被要求执行各项任务时,它需要一个脚本的整体功能。

使用函数来执行重复性的任务,是一个很好的方式来创建代码的重用。代码重用是现代面向对象编程的原则的重要组成部分。

Shell函数是类似于其他编程语言中的子程序,过程和函数。

创建函数:



声明一个函数,只需使用以下语法:

function_name () { 
   list of commands
}

函数名 function_name,这就是你将使用它从其他地方在你的脚本调用。函数名必须遵循括号内,后括号内的命令的列表。

例如:



以下是使用函数简单的例子:

#!/bin/sh

# Define your function here
Hello () {
   echo "Hello World"
}

# Invoke your function
Hello

当你想执行上面的脚本,它会产生以下结果:

$./test.sh
Hello World
$

参数传递给函数:



你可以定义一个函数,它接受参数,而调用这些函数。将这些参数代表$1,$2,依此类推。

以下是一个例子,我们传递两个参数Zara和Ali ,然后我们捕获和打印这些参数函数。

#!/bin/sh

# Define your function here
Hello () {
   echo "Hello World $1 $2"
}

# Invoke your function
Hello Zara Ali

这将产生以下结果:

$./test.sh
Hello World Zara Ali
$

从函数的返回值:



如果你执行一个exit命令从一个函数内部,其效果不仅是终止执行的功能,而且Shell 程序中调用该函数。

如果你不是想,只是终止执行该函数,再有就是退出来的一个定义的函数。

根据实际情况,你可以从你的函数返回任何值,使用返回的命令,其语法如下:

return code

这里的代码可以是任何你选择这里,但很明显,你应该选择你的脚本作为一个整体的背景下是有意义的或有用的东西。

例子:



下面的函数返回一个值1:

#!/bin/sh

# Define your function here
Hello () {
   echo "Hello World $1 $2"
   return 10
}

# Invoke your function
Hello Zara Ali

# Capture value returnd by last command
ret=$?

echo "Return value is $ret"

这将产生以下结果:

$./test.sh
Hello World Zara Ali
Return value is 10
$

嵌套函数:



函数更有趣的功能之一是,他们可以调用本身以及调用其他函数。被称为递归函数调用自身的函数。

经过简单的例子演示了一个嵌套的两个函数:

#!/bin/sh

# Calling one function from another
number_one () {
   echo "This is the first function speaking..."
   number_two
}

number_two () {
   echo "This is now the second function speaking..."
}

# Calling function one.
number_one

这将产生以下结果:

This is the first function speaking...
This is now the second function speaking...

从提示的函数调用:



你可以把常用功能 .profile 的定义,这样他们就会每当登录,在命令提示符下,您可以使用它们。

或者,你可以在一个文件中的定义分组为 test.sh,然后通过键入当前shell中执行该文件:

$. test.sh

这样做的效果造成任何test.sh内定义的函数,可以阅读在如下定义为当前shell:

$ number_one
This is the first function speaking...
This is now the second function speaking...
$

要删除从 shell 函数的定义,可以使用unset命令 .f 选项。这是相同的命令来删除一个变量的定义Shell。

$unset .f function_name


Shell 联机帮助


所有的Unix命令来与一些可选的和强制性的选择。忘记这些命令的完整语法,这是很常见。

因为没有人能记得每一个UNIX命令和选项,一直提供在线帮助,因为在Unix 早期的时候。

Unix的版本的帮助文件,被称为手册页。如果你知道任何命令的名字,但你不知道如何使用它,那么手册页来帮助你。

语法



下面是一个简单的命令来获得系统工作,而任何Unix命令的细节:

$man command

例子:



现在,你能想象的任何命令,你想要得到的帮助。假设你想知道关于pwd ,那么你只需要使用下面的命令:

$man pwd

上面的命令将打开一个帮助你会给你pwd命令的完整信息。亲自试一试在你的命令提示符下,以获得更多的细节

你可以得到完整的细节上man命令本身使用下面的命令:

$man man

手册页部分:



手册页一般分为部分,一般的man page作者偏好变化。下面是一些较常见的部分:

部分 描述
NAME Name of the command
SYNOPSIS General usage parameters of the command.
DESCRIPTION Generally describes of the command and what it does
OPTIONS Describes all the arguments or options to the command
SEE ALSO Lists other commands that are directly related to the command in the man page or closely resembling its functionality.
BUGS Explains any known issues or bugs that exist with the command or its output
EXAMPLES Common usage examples that give the reader an idea of how the command can be used.
AUTHORS The author of the man page/command.

最后,我要说的是手册页是一个重要的研究资源和第一途径,当你需要在Unix系统信息的命令或文件。

有用的Shell命令:



现在你知道如何着手,链接后会给你一个最重要和最频繁使用的Unix Shell命令列表。

如果你不知道如何使用的任何命令,然后使用手册页获取有关命令的完整细节。

这里是清单 shell - 有用的命令


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值