1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > shell脚本基础(环境变量 重定向 数学运算 退出脚本)

shell脚本基础(环境变量 重定向 数学运算 退出脚本)

时间:2018-07-24 16:42:39

相关推荐

shell脚本基础(环境变量 重定向 数学运算 退出脚本)

一、使用环境变量

1、环境变量

所谓环境变量,就是用来存储有关shell会话和工作环境信息的特性,这项特性允许你在内存中存储数据,以便程序或shell中运行的脚本能够轻松访问到它们。这也是存储持久数据的一种简便方法。

环境变量分为 : 全局环境变量、局部环境变量

(1)全局环境变量

全局环境变量对于shell会话和所有生成的子shell都是可见的。

我们可以使用env或printenv命令查看全局变量,要显示个别环境变量的值,可以使用printenv命令,也可以使用echo命令,在这种情况下引用某个环境变量的时候,必须在变量前面加上一个美元符($)。

[root@:101.251.254.6 shell]#env//显示做了删减,太多了HOSTNAME=SHELL=/bin/bashUSER=root......HOME=/rootLOGNAME=root......[root@:101.251.254.6 shell]#printenvHOSTNAME=SHELL=/bin/bashTERM=xtermUSER=root......HOME=/rootLOGNAME=root......[root@:101.251.254.6 shell]#printenv SHELL//查看环境变量值/bin/bash[root@:101.251.254.6 shell]#echo $SHELL/bin/bash[root@:101.251.254.6 shell]#env SHELLenv: SHELL: No such file or directory

(2)局部环境变量

局部环境变量只能在定义它们的进程中可见。但是在Linux系统并没有一个只显示局部环境变量的命令。set命令会显示为某个特定进程设置的所有环境变量,包括局部变量、全局变量以及用户定义变量。

[root@:101.251.254.6 shell]#setBASH=/bin/bash......BASH_ALIASES=()BASH_ARGC=()BASH_ARGV=()BASH_CMDS=()BASH_LINENO=()BASH_SOURCE=()......

所有通过printenv命令能看到的全局环境变量都出现在了set命令的输出中。

但在set命令的输出中还有其他一些环境变量,即局部环境变量和用户定义变量。

2、用户自定义变量

(1)局部用户定义变量

我们可以在shell进程内创建可见的局部变量,可以通过等号给环境变量赋值,值可以是数值或字符串。系统环境变量是默认大写的,自己创建的局部变量或是shell脚本,最好使用小写字母,这能够避免重新定义系统环境变量可能带来的灾难。

[root@:101.251.254.6 shell]#echo $my_variable[root@:101.251.254.6 shell]#my_variable=Hello[root@:101.251.254.6 shell]#echo $my_variableHello[root@:101.251.254.6 shell]#my_variable="Hello World"//赋值含空格时带引号[root@:101.251.254.6 shell]#echo $my_variableHello World

设置局部环境变量后,就能在shell进程的任何地方使用它了。但是,如果生成了另外一个shell,它在子shell中就不可用。当你退出子shell并回到原来的shell时,这个局部环境变量依然可用。

类似地,如果你在子进程中设置了一个局部变量,那么一旦你退出了子进程,那个局部环境变量就不可用。

[root@:101.251.254.6 shell]#echo $my_variableHello World ![root@:101.251.254.6 shell]#bash//进入子shell[root@:101.251.254.6 shell]#echo $my_variable//my_variable局部变量不可用[root@:101.251.254.6 shell]#echo $my_test//定义my_test局部变量[root@:101.251.254.6 shell]#my_test=123[root@:101.251.254.6 shell]#echo $my_test123[root@:101.251.254.6 shell]#exitexitYou have new mail in /var/spool/mail/root[root@:101.251.254.6 shell]#echo $my_variableHello World ![root@:101.251.254.6 shell]#echo $my_test//子shell定义的my_variable局部变量不可用

(2)全局用户定义变量

export命令可以将局部环境变量定义为全局环境变量,且修改子shell中全局环境变量并不会影响到父shell中该变量的值。

[root@:101.251.254.6 shell]#my_variable="Global"[root@:101.251.254.6 shell]#export my_variable//定义为全局变量[root@:101.251.254.6 shell]#echo $my_variableGlobal[root@:101.251.254.6 shell]#bash//进入子shell[root@:101.251.254.6 shell]#echo $my_variableGlobal[root@:101.251.254.6 shell]#my_variable=test//修改[root@:101.251.254.6 shell]#echo $my_variabletest[root@:101.251.254.6 shell]#exitexit[root@:101.251.254.6 shell]#echo $my_variable//不影响父shellGlobal

删除环境变量,同样,我们需要在父shell中删除,在子shell中删除也不会反映到父shell。

[root@:101.251.254.6 shell]#echo $my_variableGlobal[root@:101.251.254.6 shell]#unset my_variable[root@:101.251.254.6 shell]#echo $my_variable

二、构建基本脚本

1、显示消息

echo命令是shell脚本中与用户交互的重要工具。你会发现在很多地方都能用到它,尤其是需要显示脚本中变量的值的时候。

echo命令可用单引号或双引号来划定文本字符串。如果在字符串中用到了它们,你需要在文本中使用其中一种引号,而用另外一种来将字符串划定起来。像下面这样:

[root@:101.251.254.6 shell]#echo "Let's go"Let's go[root@:101.251.254.6 shell]#echo 'This method called "Comparative"'This method called "Comparative"

要把文本字符串和命令输出显示在同一行中,该怎么办呢?可以用echo语句的-n参数

[root@vg-adn-adxCreateImageAli:47.90.255.30 haha]#cat test1.sh#! /bin/bash#This script displays the date and who's logged onecho -n "The Time: "//-n将文本和输出显示在同一行dateecho "Who's logged:"who[root@vg-adn-adxCreateImageAli:47.90.255.30 haha]#sh test1.shThe Time: Tue Jul 23 17:02:30 CST //文本和输出在一行Who's logged:mobsa pts/0 -07-23 14:34 (61.34.166.62)

2、使用变量

shell维护着一组环境变量,用来记录特定的系统信息。比如系统的名称、登录到系统上的用户名、用户的系统ID(也称为UID)、用户的默认主目录以及shell查找程序的搜索路径。可以用set命令来显示一份完整的当前环境变量列表。

[root@vg-adn-adxCreateImageAli:47.90.255.30 haha]#cat test2.sh#! /bin/bash#This script displays user's informationecho USER:$USERecho UID:$UIDecho HOME:$HOME[root@vg-adn-adxCreateImageAli:47.90.255.30 haha]#sh test2.shUSER:rootUID:0HOME:/root

echo命令中的环境变量会在脚本运行时替换成当前值。如,我们$USER系统变量放置到双引号中,而shell依然能够知道我们的意图。但只要脚本在引号中出现美元符,它就会以为你在引用一个变量。在这个例子中,脚本会尝试显示变量$1(但并未定义),再显示数字5。要显示美元符,你必须在它前面放置一个反斜线。

[root@vg-adn-adxCreateImageAli:47.90.255.30 haha]#echo "User info for userid:$USER"User info for userid:root[root@vg-adn-adxCreateImageAli:47.90.255.30 haha]#echo "The cost is $15"The cost is 5[root@vg-adn-adxCreateImageAli:47.90.255.30 haha]#echo "The cost is \$15"The cost is $15

shell脚本还允许在脚本中定义和使用自己的变量。定义变量允许临时存储数

据并在整个脚本中使用。

[root@vg-adn-adxCreateImageAli:47.90.255.30 haha]#cat test3.sh#!/bin/bash# testing variablesdays=10guest="Katie"echo "$guest checked in $days days ago"days=5guest="Jessica"echo "$guest checked in $days days ago"[root@vg-adn-adxCreateImageAli:47.90.255.30 haha]#sh test3.shKatie checked in 10 days agoJessica checked in 5 days ago

shell脚本中最有用的特性之一就是可以从命令输出中提取信息,并将其赋给变量。把输出赋给变量之后,就可以随意在脚本中使用了。这个特性在处理脚本数据时尤为方便。

有两种方法可以将命令输出赋给变量:

反引号字符(`)$()格式

示例1 : shell会运行命令替换符号中的命令,并将其输出赋给变量testing。注意,赋值等号和命令替换字符之间没有空格。

[root@vg-adn-adxCreateImageAli:47.90.255.30 haha]#cat test4.sh#!/bin/bashtesting=$(date)echo "The date and time are: " $testing[root@vg-adn-adxCreateImageAli:47.90.255.30 haha]#sh test4.shThe date and time are: Tue Jul 23 17:35:15 CST

示例2 : 提取日期信息来生成日志文件名

+%y%m%d格式告诉date命令将日期显示为两位数的年月日的组合,在脚本中通过命令替换获得当前日期并用它来生成唯一文件名。目录中出现的日志文件采用$today变量的值作为文件名的一部分。日志文件的内容是/usr/bin目录内容的列表输出。

[root@vg-adn-adxCreateImageAli:47.90.255.30 haha]#date +%y%m%d190723[root@vg-adn-adxCreateImageAli:47.90.255.30 haha]#cat test5.sh#!/bin/bash# copy the /usr/bin directory listing to a log filetoday=$(date +%y%m%d)ls /usr/bin -al > log.$today[root@vg-adn-adxCreateImageAli:47.90.255.30 haha]#sh test5.sh[root@vg-adn-adxCreateImageAli:47.90.255.30 haha]#lslog.190723 test1.sh test2.sh test3.sh test4.sh test5.sh

3、重定向、追加和管道

(1)输入/出重定向、追加

[root@vg-adn-adxCreateImageAli:47.90.255.30 haha]#date > test6//输出重定向[root@vg-adn-adxCreateImageAli:47.90.255.30 haha]#cat test6Tue Jul 23 17:48:23 CST [root@vg-adn-adxCreateImageAli:47.90.255.30 haha]#who > test6[root@vg-adn-adxCreateImageAli:47.90.255.30 haha]#cat test6mobsa pts/0 -07-23 14:34 (61.34.166.62)[root@vg-adn-adxCreateImageAli:47.90.255.30 haha]#date >> test6//追加[root@vg-adn-adxCreateImageAli:47.90.255.30 haha]#cat test6mobsa pts/0 -07-23 14:34 (61.34.166.62)Tue Jul 23 17:49:26 CST [root@vg-adn-adxCreateImageAli:47.90.255.30 haha]#wc < test6//输入重定向2 11 83[root@vg-adn-adxCreateImageAli:47.90.255.30 haha]#wc test6

//wc命令可以对对数据中的文本进行计数。默认情况下,它会输出3个值:

文本的行数文本的词数文本的字节数

(2)管道

管道被放在命令之间,将一个命令的输出重定到另一个命令中:

command1 | command2

不要以为由管道串起的两个命令会依次执行。Linux系统实际上会同时运行这两个命令,在系统内部将它们连接起来。在第一个命令产生输出的同时,输出会被立即送给第二个命令。数据传输不会用到任何中间文件或缓冲区。

[root@vg-adn-adxCreateImageAli:47.90.255.30 haha]#rpm -qa | sortacl-2.2.49-7.el6_9.1.x86_64alsa-lib-1.1.0-4.el6.x86_64......

除非你的眼神特别好,否则可能根本来不及看清楚命令的输出。由于管道操作是实时运行的,所以只要rpm命令一输出数据,sort命令就会立即对其进行排序。等到rpm命令输出完数据,sort命令就已经将数据排好序并显示了在显示器上。

我们可以在一条命令中使用任意多条管道。可以持续地将命令的输出通过管道传给其他命令来细化操作。在这个例子中,sort命令的输出会一闪而过,所以可以用一条文本分页命令(例如less或more)来强行将输出按屏显示。

[root@vg-adn-adxCreateImageAli:47.90.255.30 haha]#rpm -qa | sort | less

也可以搭配使用重定向和管道来将输出保存到文件中。

[root@vg-adn-adxCreateImageAli:47.90.255.30 haha]#rpm -qa | sort > rpm.list[root@vg-adn-adxCreateImageAli:47.90.255.30 haha]#more rpm.listacl-2.2.49-7.el6_9.1.x86_64alsa-lib-1.1.0-4.el6.x86_64......

4、数学运算

最开始,Bourne shell提供了一个特别的命令用来处理数学表达式:expr命令,允许在命令行上处理数学表达式,但是特别笨拙。对于那些容易被shell错误解释的字符,在它们传入expr命令之前,需要使用shell的转义字符(反斜线\)将其标出来,否则会报错。

[root@vg-adn-adxCreateImageAli:47.90.255.30 haha]#expr 5 * 7expr: syntax error[root@vg-adn-adxCreateImageAli:47.90.255.30 haha]#expr 5 \* 735[root@vg-adn-adxCreateImageAli:47.90.255.30 haha]#expr 5 | 0//或-bash: 0: command not found[root@vg-adn-adxCreateImageAli:47.90.255.30 haha]#expr 5 \| 05

同样,在shell脚本中使用expr命令也比较麻烦

[root@vg-adn-adxCreateImageAli:47.90.255.30 haha]#cat test6.sh#!/bin/bash# An example of using the expr commandvar1=3var2=7var3=$(expr $var2 \* $var1)echo The result is $var3[root@vg-adn-adxCreateImageAli:47.90.255.30 haha]#sh test6.shThe result is 21

bash shell提供了一种更简单的方法来执行数学表达式。在bash中,在将一个数学运算结果赋给某个变量时,可以用美元符和方括号($[ operation ])将数学表达式围起来。

[root@vg-adn-adxCreateImageAli:47.90.255.30 haha]#var1=$[3 * 7][root@vg-adn-adxCreateImageAli:47.90.255.30 haha]#echo $var121

用方括号执行shell数学运算比用expr命令方便很多,这种技术也适用于shell脚本。

[root@vg-adn-adxCreateImageAli:47.90.255.30 haha]#cat test7.sh#!/bin/bashvar1=100var2=50var3=45var4=$[$var1 * $[$var2 - $var3]]//可以替换为var4=$[$var1 * ($var2 - $var3)]echo The final result is $var4[root@vg-adn-adxCreateImageAli:47.90.255.30 haha]#sh test7.shThe final result is 500

bash shell数学运算符只支持整数运算。有几种解决方案能够克服bash中数学运算的整数限制。最常见的方案是用内建的bash计算器,叫作bc。

bc中,浮点运算是由内建变量scale控制的。必须将这个值设置为你希望在计算结果中保留的小数位数,否则无法得到期望的结果。

[root@vg-adn-adxCreateImageAli:47.90.255.30 haha]#bcbc 1.06.95Copyright 1991-1994, 1997, 1998, 2000, , Free Software Foundation, Inc.This is free software with ABSOLUTELY NO WARRANTY.For details type `warranty'.3.44/50scale=3//保留三位小数3.44/5.688quit

在脚本中使用bc

[root@vg-adn-adxCreateImageAli:47.90.255.30 haha]#cat test8.sh#!/bin/bashvar1=$(echo "scale=4;3.44 / 5" | bc)echo The answer is $var1[root@vg-adn-adxCreateImageAli:47.90.255.30 haha]#sh test8.shThe answer is .6880

一旦变量被赋值,那么,这个变量也可以用于其他运算。

[root@vg-adn-adxCreateImageAli:47.90.255.30 haha]#cat test9.sh#!/bin/bashvar1=20var2=3.141var3=$(echo "scale=3; $var1 * $var2" | bc)var4=$(echo "scale=3; $var3 * $var2" | bc)echo result=$var4[root@vg-adn-adxCreateImageAli:47.90.255.30 haha]#sh test9.shresult=197.317

这个方法适用于较短的运算,但有时你会涉及更多的数字。如果需要进行大量运算,在一个命令行中列出多个表达式就会有点麻烦。最好的办法是使用内联输入重定向,它允许你直接在命令行中重定向数据。EOF文本字符串标识了内联重定向数据的起止。

[root@vg-adn-adxCreateImageAli:47.90.255.30 haha]#cat test10.sh#!/bin/bashvar1=10.2var2=7.7var3=5.03var4=21var5=$(bc << EOFscale=4a=$var2 * $var1b=$var4 * $var3a + bEOF)echo "Result is $var5"[root@vg-adn-adxCreateImageAli:47.90.255.30 haha]#sh test10.shResult is 184.17

5、退出脚本

上面的脚本示例中,运行完最后一条命令时,脚本就结束了。其实还有另外一种更优雅的方法可以为脚本划上一个句号。

shell中运行的每个命令都使用退出状态码(exit status)告诉shell它已经运行完毕。退出状态码是一个0~255的整数值,在命令结束运行时由命令传给shell。可以捕获这个值并在脚本中使用。

Linux提供了一个专门的变量$?来保存上个已执行命令的退出状态码。我们了解一下常见的退出状态码 :

[root@:101.251.254.6 shell]#dateWed Jul 31 09:57:16 CST [root@:101.251.254.6 shell]#echo $?//0表示命令成功结束0[root@:101.251.254.6 shell]#asdfg-bash: asdfg: command not found[root@:101.251.254.6 shell]#echo $?//127表示无效命令127[root@:101.251.254.6 shell]#date -t//-t是无效参数date: invalid option -- 't'Try `date --help' for more information.You have new mail in /var/spool/mail/root[root@:101.251.254.6 shell]#echo $?//一般性未知错误,退出状态码为11

默认情况下,shell脚本会以脚本中的最后一个命令的退出状态码退出。exit命令允许你在脚本结束时指定一个退出状态码。

[root@:101.251.254.6 shell]#cat test.sh#!/bin/bash# testing the exit statusvar1=10var2=30var3=$[$var1 + $var2]echo The answer is $var3exit 5[root@:101.251.254.6 shell]#sh test.shThe answer is 40[root@:101.251.254.6 shell]#echo $?5

也可以在exit命令的参数中使用变量。

[root@:101.251.254.6 shell]#cat test.sh#!/bin/bash# testing the exit statusvar1=10var2=30var3=$[$var1 + $var2]echo The answer is $var3exit $var3[root@:101.251.254.6 shell]#sh test.shThe answer is 40[root@:101.251.254.6 shell]#echo $?40

注意的是,因为退出状态码最大只能是255。所以当指定值大于255时,shell会对其做模256的运算,看一个例子 :

[root@:101.251.254.6 shell]#cat test.sh#!/bin/bash# testing the exit statusvar1=10var2=30var3=$[$var1 * $var2]echo The answer is $var3exit $var3[root@:101.251.254.6 shell]#sh test.shThe answer is 300[root@:101.251.254.6 shell]#echo $?//退出状态码为300mod25644

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。