shell内置命令,shell编程基础命令

  shell内置命令,shell编程基础命令

  命令

  我们从Shell脚本内部执行两种类型的命令。也就是普通的命令,我们也可以在命令行上运行,叫做本地命令,另一种是内置命令,叫做内部命令。内置命令在Shell内部实现,不能被外部程序调用。但是,大多数内部命令将作为相对独立的单个程序提供,这也是POSIX标准的一部分。一般来说,内部命令和外部命令差别不大,除非内部命令运行起来更高效。

  但是,这里我们将只讨论一些主要的命令,包括我们在编写脚本时需要使用的外部和内部命令。作为一个Linux用户,我们会知道其他一些可以在命令行上运行的命令。我们应该记住,除了这里提到的一些内置命令,我们还可以使用脚本中已知的一些其他命令。

  破裂

  当我们想退出for、while或until循环时,可以使用这个命令。我们也可以通过另一个数值参数来break,这个数值参数正好是我们想要退出的循环数。因为这将使我们的脚本难以阅读,我们不建议您使用这种方法。默认情况下,break只会退出一个级别。比如下面这个例子:

  #!/bin/sh

  rm -rf弗雷德*

  回声频率1

  回声fred2

  mkdir fred3

  回声fred4

  用于fred*中的文件

  做

  if[-d " $ file "];然后

  打破;

  船方不负担装货费用

  完成的

  回显第一个目录开始弗雷德是$file

  rm -rf弗雷德*

  出口0

  :命令

  冒号命令只是一个空命令。这个命令作为true的别名来简化逻辑条件是非常有用的。因为是内置命令,所以运行速度比true快,但是输出不容易理解。

  我们可以看到在while循环中使用了这个命令。While:可以代替比较常见的while true来实现无限循环。

  :结构在设置变量的条件时也很有用,例如:

  :${var:=value}

  如果没有:shell将尝试把$var作为一个命令。

  #!/bin/sh

  rm -f弗雷德

  if [ -f弗雷德];然后

  :

  其他

  回显文件fred不存在

  船方不负担装货费用

  出口0

  继续

  类似于C语言,这个命令可以使变量在for,while,直到继续执行下一个循环使用列表中的下一个值。

  #!/bin/sh

  rm -rf弗雷德*

  回声频率1

  回声fred2

  mkdir fred3

  回声fred4

  用于fred*中的文件

  做

  if[-d " $ file "];然后

  回显“跳过目录$文件”

  继续

  船方不负担装货费用

  回显文件是$file

  完成的

  rm -rf弗雷德*

  出口0

  continue命令后面可以跟一个数字作为可选参数,这样我们就可以部分跳出嵌套循环。但是,这样的参数并不常用,因为它会使我们的脚本难以理解。例如:

  对于1 2 3年的x

  做

  在$x前回显

  继续1

  在$x后回显

  完成的

  该脚本的输出如下:

  1之前

  2点之前

  3点前。命令。该命令将在当前Shell中执行该命令:/shell _脚本

  通常,当脚本执行外部命令或脚本时,它会创建一个新的循环或子外壳。这个外部命令将在新环境中运行,但是这个新环境将忽略返回给父Shell的返回代码。但是外部资源和。让被调用脚本中列出的命令在相同的环境中运行。

  这意味着在正常情况下,该命令对环境变量所做的更改将会丢失。另一方面。该命令可以允许被执行的命令改变当前的运行周期。当我们想要使用脚本作为包装器来为稍后运行的其他命令设置环境时,这是非常有用的。例如,如果我们同时处理几个不同的项目,有时我们会发现我们需要用不同的参数调用一个命令,也许是调用一个旧版本的编译器来维护一个旧程序。

  在Shell脚本中。(点)命令的工作方式类似于C或C中的#include。虽然它并不真正包含脚本,但它确实在当前条件下运行该命令,因此我们可以使用该命令来合并脚本中变量或函数的定义。

  在下面的例子中,我们在命令行中使用了dot命令,但是我们也可以在脚本中使用这个命令。

  假设我们有两个文件,这两个文件包含两个不同开发环境的环境设置。要为旧的经典命令classic_set设置环境,我们可以使用以下命令:

  #!/bin/sh

  版本=经典

  PATH=/usr/local/old _ bin:/usr/bin:/bin:

  PS1="经典"

  2对于新命令,我们使用latest_set:

  #!/bin/sh

  版本=最新

  PATH=/usr/local/new _ bin:/usr/bin:/bin:

  PS1="最新版本"

  我们可以使用dot命令合并这些脚本来设置环境,如下所示:

  $ ./经典_集

  经典echo $版本

  经典的

  经典。最新_集

  最新版本echo $version

  最近的

  最新版本

  回声

  虽然printf命令只在现代Shell中使用,但在这里我们仍然遵循通常的习惯,使用echo命令的字符串后跟新的一行字符。

  一个常见的问题是如何禁止换行字符。不幸的是,不同版本的Unix实现了不同的解决方案。Linux中的常见做法是:

  echo -n "要输出的字符串"

  但也许我们经常会看到以下情况:

  echo -e "字符串到输出/c "

  在第二种方法中,echo -e确保某些转义字符被允许解释,例如,new /t被解释为tab,而/n被解释为回车和换行。这通常是默认设置。

  evaluate 评价

  eval命令允许我们分配参数。它是Shell的内置命令,不作为单独的命令存在。下面这个借用X/Open的简短例子可以很好的说明这个问题。

  foo=10

  x=foo

  y=$$x

  回声$y

  这个例子的输出结果是$foo。然而,如果我们使用下面的例子:

  foo=10

  x=foo

  eval y=$$x

  回声$y

  因此输出结果是10。所以eval有类似于另一个$:它将为我们提供一个变量的值。

  eval命令非常有用。它将允许我们随时创建和运行代码。诚然,他会让剧本变得高度复杂,但他会允许我们做一些通常非常困难甚至不可能的事情。

  高级管理人员

  exec命令有两种不同的用法。他最常见的用法是用不同的程序替换当前的Shell。比如说;

  高管墙“感谢所有的鱼”

  在脚本中将使用wall命令来替换当前的Shell。不会处理exec命令之后的脚本内容,因为执行该脚本的Shell已经不存在了。

  exec的第二个用途是修改当前文件的描述符:

  exec 3文件

  结果是打开文件描述符,从文件file中读入内容。3.这种用法并不常见。

  出口n

  exit命令使脚本返回返回代码。如果我们在交互式Shell中运行这个命令,它将使我们退出会话。如果我们不指定我们的脚本在没有指定返回状态的情况下退出,那么脚本中最后一个命令的执行结果将作为返回值。指定返回值通常是一种好的做法。

  在Shell编程中,返回码0是成功,1到125是错误代码,脚本可以使用。的保留值具有保留的含义:

  26该文件不可执行。

  27未找到命令。

  出现28个及以上信号。

  使用0作为成功代码对于许多C或C程序员来说会有些不同。这样做的最大好处是,它允许我们在脚本中使用125个用户定义的错误代码,而无需全局错误代码变量。

  在下面的示例中,如果它存在于当前目录中。该配置文件返回一个成功值。

  #!/bin/sh

  if[-f . profile];然后

  出口0

  船方不负担装货费用

  1号出口

  如果我们是一个愿意被惩罚的人,或者需要简洁的脚本,我们可以用之前见过的AND和OR列表重写我们的脚本,把所有内容放在一行:

  [-f . profile]0号出口 1号出口

  出口

  export命令可以命令变量及其子壳中的参数。默认情况下,在一个Shell中创建的变量在另一个名为。export命令可以创建一个带有参数的环境变量,该变量对于当前程序中调用的其他脚本或程序是可见的。从技术上讲,任何子程序引入的环境变量都是从这个Shell中派生出来的。下面的两个脚本export1和export2可以很好地演示这个命令的含义和用法。

  我们先列出export2的脚本内容:

  #!/bin/sh

  echo "$foo "

  回显" $bar "

  以下是export1中的内容。在这个脚本的最后,我们调用export2:

  #!/bin/sh

  foo="第一个元语法变量"

  export bar="第二个元语法变量"

  导出2

  如果我们运行这个脚本,我们可以得到以下结果:

  $ export1

  第二个元语法变量

  $

  第一行出现空行是因为变量foo在export2中不可见,所以$foo被赋值为null值。如果你输出一个空变量,你会得到一个新的行。

  一旦一个变量被一个Shell引入,它就在这个Shell派生的脚本中可见,或者依次在这个Shell中被调用。如果脚本export2调用另一个脚本,该变量的值对另一个脚本仍然可见。

  命令set -a或set -allexport可以引入所有变量。

  表达式

  expr命令将其参数视为表达式。它最常见的用法是在简单的算术中,如下所示:

  x=表达式$x 1

  这里的反引号(`)是命令expr $x 1作为变量x的值的结果,我们也可以不用反引号形式,用语法$()来写这个句子,比如下面的形式:

  x=$(表达式$x 1)

  expr命令相当强大,可以处理很多表示赋值的问题。下表列出了他的一些原则:

  Expr1 expr2如果Expr1不为空,则为expr1,否则为expr2。

  如果expr2或Expr1为零,则Expr1 expr2为零,否则为expr1。

  Expr1=expr2相等

  Exp1expr2大于

  Expr1=expr2大于或等于

  Exp1expr2小于

  Expr1=expr2小于或等于

  expr1!=expr2不等于

  Exp1expr2加法

  Expr1-expr2减法

  表达式1 *表达式2乘法

  Expr1/expr2整数除法

  Expr1% expr2整数模

  打印函数

  printf命令只在现代Shell中可用。X/Open建议我们应该使用echo来生成格式化的输出。

  语法如下:

  printf“格式字符串”参数1参数2.

  字符串的格式类似于C或C中的格式,但是有一些限制。主要区别在于Shell支持浮点数,因为Shell中的所有算术运算都被视为整数。格式化字符串可以由字母、转义序列和转义字符的任意组合组成。格式化字符串中除%和/以外的所有字符都可以准确输出。

  下面列出了可以支持的转义序列:

  //反斜杠

  /一个警告

  /b退格键

  /f以形成输入字符

  /n换行符

  /r输入

  /t制表符

  /v垂直制表符

  /ooo用八进制表示的单个字符。

  转义字符相当复杂,所以这里我们只是列出一些我们会经常用到的东西。更详细的内容可以在在线bash手册中获得。转义字符由%和紧随其后的要转义的字符组成。以下是一些主要的转义字符:

  输出十进制数

  输出一个字符。

  输出一个字符串。

  %输出%个字符

  然后我们将使用格式化字符串来解释其余的参数并输出结果。例如:

  $ printf“% s/n”您好

  你好

  $ printf "%s %d/t%s " "你好" 15个人

  嗨,有15个人

  这里我们应该注意,我们必须使用使hitthere字符串成为单个参数。

  返回

  return命令使函数返回。我们在以前的一些函数的使用中已经注意到了这一点。return命令返回一个数值参数,该参数在调用该函数的脚本中可见。如果没有指定return参数,return将默认返回最后一个命令的返回代码。

  设置

  set命令为Shell设置参数变量。这是在输出命令时使用字段的一种有用方式,用空格分隔。

  假设我们想在Shell脚本中使用当前月份的名称。系统提供了一个date命令,它包含了月份作为一个字符串,但是我们需要把它和其他区域分开。我们可以使用set命令和$(.)结构来执行日期命令并返回结果。date命令的输出将月份字符串作为第二个参数。

  比如下面这个例子:

  #!/bin/sh

  回显日期是$(日期)

  设置$(日期)

  echo每月2美元

  出口0

  这个程序为date命令的输出设置参数列表,并使用第二个参数$2来获取月份的名称。

  在这里,我们应该注意,我们使用date命令作为一个简单的例子来说明如何求解position参数。因为date命令与语言设置有关,实际上我们可以使用date %B命令来获取月份的名称。date还有很多其他格式选项,我们可以从他的man页面获得更详细的说明。

  我们还可以使用set命令,通过传递Shell参数来控制Shell执行模式。最常见的用法是使用命令集-x,它将使脚本显示其当前的执行轨迹。

  变化

  shift命令可以将所有参数变量的值减1,这样$2就变成了$1,$3就变成了$2,以此类推。这样,$1的值将被丢弃,而$0的值将保持不变。如果在调用shift命令时指定了数值参数,这些参数也会移动一些相应的位置。其他变量$ *、$ @、$ #也将被

  shift命令在扫描参数时非常有用。如果我们的脚本需要10个或更多的参数,那么我们需要使用shift来访问10个或更多的内容。

  例如,我们可以扫描以下形式的所有位置参数:

  #!/bin/sh

  而[ "$1 "!="" ];做

  回显" $1 "

  变化

  完成的

  出口0

  圈套

  Trap命令可用于指定收到信号时要采取的行动。一种常见的用法是在脚本被中断时进行的处理工作。由于历史原因,Shell总是使用数字来表示信号,但是新脚本可以通过#include signal.h并忽略sig前缀来使用信号的名称。如果我们想检查信号的数量及其相关名称,我们可以在命令提示符下输入trap -l命令。

  陷阱命令可以通过跟随信号的名称来传达要执行的动作:

  陷阱命令信号

  记住,脚本通常是从上到下解释的,我们必须在要保护的脚本部分之前指定trap命令。

  要将陷阱的条件设置为默认值,我们只需将命令指定为-。要忽略某个信号,我们可以将命令设置为空字符串```。不带任何参数的陷阱命令将打印出当前动作列表。

  下表列出了一些可以捕捉的重要标准X/Open信号。更多细节可从信号手册中获得。

  HUP(1)挂起。它通常在终端离线或用户注销时发出。

  INT(2)中断。它通常是通过按Ctrl+c发出的.

  退出(3)通常通过Ctrl/退出。

  ABRT(6)暂停通常是由一些严重的操作失误造成的。

  ALRM(14)警告。通常由处理超时发出。

  第(15)项结束。它通常在系统关闭时发送。

  以下脚本模拟了一些简单信号的处理过程:

  #!/bin/sh

  陷阱 rm -f /tmp/my_tmp_file_$$ INT

  回显创建文件/tmp/my_tmp_file_$$

  date /tmp/my_tmp_file_$$

  echo“按中断(CTRL-C)来中断.”

  while[-f/tmp/my _ tmp _ file _ $ $];做

  回显文件存在

  睡眠1

  完成的

  回显文件不再存在

  陷印整数

  回显创建文件/tmp/my_tmp_file_$$

  date /tmp/my_tmp_file_$$

  echo“按下中断(control-C)来中断.”

  while[-f/tmp/my _ tmp _ file _ $ $];做

  回显文件存在

  睡眠1

  完成的

  回声我们从来没有到这里

  出口0

  如果我们运行这个命令并在每个循环中按Ctrl+C,我们将得到以下输出:

  创建文件/tmp/my_tmp_file_141

  按中断(CTRL-C)来中断.

  文件存在

  文件存在

  文件存在

  文件存在

  该文件不再存在

  创建文件/tmp/my_tmp_file_141

  按中断(CTRL-C)来中断.

  文件存在

  文件存在

  文件存在

  文件存在

  工作原理:

  该脚本使用trap命令来安排在执行命令rm -f /tmp/my_tmp_file_$$时要执行的操作。然后这个脚本将进入一个循环,直到文件存在。当用户按下Ctrl C时,语句rm -f /tmp/my_tmp_file_$$被执行,然后这个循环将再次开始。因为该文件已被删除

  这个脚本将再次使用trap命令,这一次指定当INT信号出现时不执行任何命令。它将重新创建这个文件,并进入第二个循环语句。如果用户此时按下Ctrl+C,并且没有配置要执行的语句,将发生默认动作,即立即终止脚本。因为这个脚本会立即终止,所以不会执行最后的echo和exit命令。

  复原

  unset命令从当前环境中删除变量或函数。但是,对于Shell自己定义的只读变量(比如IFS)是不允许的。这个命令不常用。

  例如,下面的例子:

  #!/bin/sh

  foo="Hello World "

  echo $foo

  unset foo

  echo $foo

shell内置命令,shell编程基础命令