Linux的Shell编程之shell基本语法

 其实作为命令语言互动式地解释和执行用户输入的命令只是Shell功能的一个方面,Shell还可以用来进行程序设计,它提供了定义变量和参数的手段以及丰富的程序控制结构。使用Shell编程类似于DOS中的批处理文件,称为Shell script,又叫Shell程序或Shell命令文件。

Shell基本语法

像高级程序设计语言一样,Shell也提供说明和使用变量的功能。对Shell来讲,所有变量的取值都是一个字串,Shell程序采用$var的形式来引用名为var的变量的值。

Shell有以下几种基本类型的变量。

(1)Shell定义的环境变量:

Shell在开始执行时就已经定义了一些和系统的工作环境有关的变量,用户还可以重新定义这些变量,常用的Shell环境变量有:

HOME 用于保存注册目录的完全路径名。

PATH 用于保存用冒号分隔的目录路径名,Shell将按PATH变量中给出的顺序搜索这些目录,找到的第一个与命令名称一致的可执行文件将被执行。

TERM 终端的类型

UID 当前用户的识别字,取值是由数位构成的字串。

PWD 当前工作目录的绝对路径名,该变量的取值随cd命令的使用而变化。

PS1 主提示符,在特权用户下,默认的主提示符是#,在普通用户下,默认的主提示符是$。

PS2 在Shell接收用户输入命令的过程中,如果用户在输入行的末尾输入“/”然后回车,或者当用户按回车键时Shell判断出用户输入的命令没有结束时,就显示这个辅助提示符,提示用户继续输入命令的其余部分,默认的辅助提示符是>。

(2)用户定义的变量:

用户可以按照下面的语法规则定义自己的变量:

变量名=变量值

要注意的一点是,在定义变量时,变量名前不应加符号$,在引用变量的内容时则应在变量名前加$;在给变量赋值时,等号两边一定不能留空格,若变量中本身就包含了空格,则整个字串都要用双引号括起来。

在编写Shell程序时,为了使变量名和命令名相区别,建议所有的变量名都用大写字母来表示。

有时我们想要在说明一个变量并对它设置为一个特定值后就不在改变它的值时,可以用下面的命令来保证一个变量的只读性:

readonly 变量名

在任何时候,创建的变量都只是当前Shell的局部变量,所以不能被Shell运行的其他命令或Shell程序所利用,而export命令可以将一个局部变量提供给Shell执行的其他命令使用,其格式为:

export 变量名

也可以在给变量赋值的同时使用export命令:

export 变量名=变量值

使用export说明的变量,在Shell以后运行的所有命令或程序中都可以访问到。

(3)位置参数:

位置参数是一种在调用Shell程序的命令行中按照各自的位置决定的变量,是在程序名之后输入的参数。位置参数之间用空格分隔,Shell取第一个位置参数替换程序文件中的$1,第二个替换$2,依次类推。$0是一个特殊的变量,它的内容是当前这个Shell程序的文件名,所以,$0不是一个位置参数,在显示当前所有的位置参数时是不包括$0的。

(4)预定义变量:

预定义变量和环境变量相类似,也是在Shell一开始时就定义了的变量。所不同的是,用户只能根据Shell的定义来使用这些变量,而不能重定义它。所有预定义变量都是由$符和另一个符号组成的,常用的Shell预定义变量有:

$# 位置参数的数量。

$* 所有位置参数的内容。

$? 命令执行后返回的状态。

$$ 当前进程的进程号。

$! 后台运行的最后一个进程号。

$0 当前执行的进程名。

其中,$?用于检查上一个命令执行是否正确。(在Linux中,命令退出状态为0表示该命令正确执行,任何非0值表示命令出错。)

$$变量最常见的用途是用做暂存文件的名字以保证暂存文件不会重复。

(5)参数置换的变量:

Shell提供了参数置换功能以便用户可以根据不同的条件来给变量赋不同的值。参数置换的变量有4种,这些变量通常与某一个位置参数相联系,根据指定的位置参数是否已经设置类决定变量的取值,它们的语法和功能分别如下。

a. 变量=${参数-word}:如果设置了参数,则用参数的值置换变量的值,否则用word置换。即这种变量的值等于某一个参数的值,如果该参数没有设置,则变量就等于word的值。

b. 变量=${参数=word}:如果设置了参数,则用参数的值置换变量的值,否则把变量设置成word,然后再用word替换参数的值。注意,位置参数不能用于这种方式,因为在Shell程序中不能为位置参数赋值。

c. 变量=${参数?word}:如果设置了参数,则用参数的值置换变量的值,否则就显示word并从Shell中退出,如果省略了word,则显示标准信息。这种变量要求一定等于某一个参数的值。如果该参数没有设置,就显示一个信息,然后退出,因此这种方式常用于出错指示。

d. 变量=${参数+word}:如果设置了参数,则用word置换变量,否则不进行置换。

所有这4种形式中的“参数”既可以是位置参数,也可以是另一个变量,只是用位置参数的情况比较多。

shell基础语法有以下这几种方式:

1.变量赋值

a=123
read name
b=$(ls /home)

把命令的执行结果赋值给变量   

2.使用变量(前面用$)   

echo $a
let a=a+1

系统变量

$0 这个程序的执行名字      

$n  这个程序的第n个参数值,n=1...9      

$*  这个程序的所有参数      

$# 这个程序的参数个数      

$$ 这个程序的PID      

$! 执行上一个背景指令的PID      

$? 上一个指令的返回值

3.if语句

if [ 22 -lt 33 ]注意空格      
then      
echo 22 less than 33      
else      
echo no      
fi

4.case语句

#!/bin/bash      
echo enter a number      
read ans      
case $ans in      
1)      
echo you numer is $ans      
;;      
2)      
echo you number is 2      
;;      
[3-9])      
echo you number is $ans      
esac

5.比较运算符

运算符 描述 示例

文件比较运算符

-e filename 如果 filename 存在,则为真 [ -e /var/log/syslog ]
-d filename 如果 filename 为目录,则为真 [ -d /tmp/mydir ]
-f filename 如果 filename 为常规文件,则为真 [ -f /usr/bin/grep ]
-L filename 如果 filename 为符号链接,则为真 [ -L /usr/bin/grep ]
-r filename 如果 filename 可读,则为真 [ -r /var/log/syslog ]
-w filename 如果 filename 可写,则为真 [ -w /var/mytmp.txt ]
-x filename 如果 filename 可执行,则为真 [ -L /usr/bin/grep ]
filename1 -nt filename2 如果 filename1 比 filename2 新,则为真 [ /tmp/install/etc/services -nt /etc/services ]
filename1 -ot filename2 如果 filename1 比 filename2 旧,则为真 [ /boot/bzImage -ot arch/i386/boot/bzImage ]

字符串比较运算符 (请注意引号的使用,这是防止空格扰乱代码的好方法)

-z string 如果 string 长度为零,则为真 [ -z $myvar ]
-n string 如果 string 长度非零,则为真 [ -n $myvar ]
string1 = string2 如果 string1 与 string2 相同,则为真 [ $myvar = one two three ]
string1 != string2 如果 string1 与 string2 不同,则为真 [ $myvar != one two three ]

算术比较运算符

num1 -eq num2 等于 [ 3 -eq $mynum ]
num1 -ne num2 不等于 [ 3 -ne $mynum ]
num1 -lt num2 小于 [ 3 -lt $mynum ]
num1 -le num2 小于或等于 [ 3 -le $mynum ]
num1 -gt num2 大于 [ 3 -gt $mynum ]
num1 -ge num2 大于或等于 [ 3 -ge $mynum ]

Shell语法

变量:

在Shell中,我们在使用变量之前并不需要进行声明.相反我们可以在需要的时候进行简单的使用就可以了.在默认的情况下,所有的变量都是作为字符串进行存储的,虽然有时我们会用数字为其赋值.Shell以及其他的一些实用的转换程序会将数字字符串转换成相应的值为进行操作.在Linux系统中是要区分大小的,所以在Shell看来变量foo与Foo是不同的.

在Shell中我们要访问变量的值,我们要在变量前加上一个$.当我们要为变量赋值时,我们可以只使用变量的名字,Shell会在需要的时候进行动态创建.检测变量内容一个简单的办法就是在终端进行输出,这时要在变量前加上一个$.

在命令行中我们可以用下面的方法来设置和检测变量的值:

$ salutation=Hello
$ echo $salutation
Hello
$ salutation=”Yes Dear”
$ echo $salutation
Yes Dear
$ salutation=7+5
$ echo $salutation
7+5

我们还可使用read命令将用户的输入赋值给变量.这样就会将变量的名字作为参数并会等待用户的输入.read命令会在用户输入回车的时候结束.当从终端读入变量时我们并不需要使用引号.如下面的例子:

$ read salutation
Wie geht’s?
$ echo $salutation
Wie geht’s?

引号:

在继续我们的学习之前我们要清楚引号的作用.

通常脚本中的参数是由空白字符来分隔的,如空格,Tab或是回车.如果我们要我们的参数包含一个或是更多个参数,我们就要使用引号了.

例如变量$foo的行为要看我们使用的引号的类型了.如果我们是用双引号,在这一行执行时就会用他的值进行替换,而如果我们使用单引号就不会发生这样的替换.我们还可以使用转义字符/来除去$的特殊意义.

在通常的情况下,我们双引号来包含字符串,这样就可以防止变量被空白符所分隔,而且会用变量的值进行替换.

在下面的这个例子中我们就会看到引号对于变量输出的影响:

#!/bin/bash
myvar=”Hi there”
echo $myvar
echo “$myvar”
echo ‘$myvar’
echo /$myvar
echo Enter some text
read myvar
echo ‘$myvar’ now equals $myvar
exit 0

这个程序的输出为:

Hi there
Hi there
$myvar
$myvar
Enter some text
Hello World
$myvar now equals Hello World

工作原理

我们创建了变理myvar,并赋值为Hi there.变量的内容由命令echo显示出来,从而可以看出$字符扩展对变量内容的影响.从这输出我们可以看出双引号并不会影响变量的替换,而单引号和反斜线却会有这样的影响.我们同时使用一个read命令来从用户得到输入.

环境变量

当启动一个Shell脚本时,一些变量会由环境中的值进行初始化.在脚本中这些变量通常为大写字母,从而与用户定义的变量进行区分,而用户定义的变理常用小写字母来表示.创建的变量依赖于我们个人的配置.其中的许多列在手册页中,但是基本的一些列在下面的表中:

$HOME    当前用户的主目录

$PATH    用来进行命令查找的由冒号分隔的目录列表

$PS1    命令提示,通常为$,但是在bash中我们可以使用更为复杂的值.例如,字符串[/u@/h /W]$是流行的默认用法来告诉我们当前的用户,机器名称以及当前的工作目录,同时给出$提示.

$PS2    第二提示符,当提示额外的输入时使用,通常为>

$IFS    输入区域分隔符.当Shell读入输入时会使用一个字符列表来分隔输入的单词,通常是空格,tab和新行字符.

$0    Shell脚本的名称.

$#    传递的参数个数.

$$    脚本的进程ID,通常用在一个脚本内部用来建立唯一的一个临时文件,如/tmp/tmp-file_$$.

如果我们的脚本调用一些参数,那么会建立一些其他的变量.即使没有传递参数,环境变量$#仍然存在,但是值却为0.

参数变量列在下面这个表中:

$1,$2,...    传递给脚本的参数.

$*    以单变量的形式显示所有的参数列表,由环境变量IFS中的第一个字符分隔.

$@    $*的一个灵巧变形.他并不使用IFS环境变量,所以如果IFS为空那么所有的所有的参数会一起运行.

我们可以通过下面的测试容易的看出$@和$*的区别:

$ IFS=’’
$ set foo bar bam
$ echo “$@”
foo bar bam
$ echo “$*”
foobarbam
$ unset IFS
$ echo “$*”
foo bar bam

正如我们所看到的,在双引号内,$@将参数进行分隔显示,而与IFS的值无关.通常来说,如果我们要访问参数,$@是一个很灵敏的选择.

我们不仅可以用echo命令打印出变量的内容,而且我们可以使用read命令来读取他们的内容.

参数和环境变量

下面的脚本展示了简单变量的处理.在我们输入了下面的脚本内容并保存为try_var,我们一定要记得用命令chmod +x try_var为其加上可执行权限.

#!/bin/sh
salutation=”Hello”
echo $salutation
echo “The program $0 is now running”
echo “The second parameter was $2”
echo “The first parameter was $1”
echo “The parameter list was $*”
echo “The user’s home directory is $HOME”
echo “Please enter a new greeting”
read salutation
echo $salutation
echo “The script is now complete”
exit 0

如果我们运行这个脚本我们会得到下面的输出:

~$ ./try_var.sh foo bar baz
Hello
The program ./try_var.sh is now running
The second parameter was bar
The first parameter list was foo bar baz
The user's home directory is /home/mylxiaoyi
Please enter a new greeting
hello
The script is now complete

工作原理:

这个脚本创建了一个名为salutation的变量并显示他的内空,然后显示了各种参数变量,而环境变量$HOME已经存在并且已经有适当的值.

函数:

所有程序语言的基本原则是测试条件并在这些测试的基础上进行各种不同的操作.在我们讨论这个话题之前,我们先来看一下在Shell脚本中我们会用到的函数构造以及我们要使用的控制结构.

一个Shell脚本可以测试由命令行调用的任何命令的返回代码,包括我们自己书写的脚本.这就是我们在每一个Shell脚本最后包含exit代码的重要原因.

test或[命令:

事实上,大多数的脚本大量的使用了Shell真假检测的test或是[命令.在大多数的系统上,[和test命令是同义的,但是当使用了一个[命令时而同时为了可读在末尾使用了一个]命令.使用[命令看起来有一点奇怪,但是这个命令在代码中会使得命令的语法看起来要简单,整洁,并且与其他的程序语言很相像.

ls -l /usr/bin/[-rwxr-xr-x 1 root root 25040 2005-11-16 21:17 /usr/bin/[

我们会使用一个简单的测试例子来介绍test命令:检测一个文件是否存在.用于这个目的的命令是test -f <filename>,所以我们可以用下面的脚本:

if test -f fred.c
then
...
fi

我们也可以像下面的样子来写:

if [ -f fred.c ]
then
...
fi

test命令的返回代码(条件是否满足)决定于条件代码是否运行.

在这里我们要注意是我们必须在[和条件之间用空格进行分隔.我们可以用下面的方法来记住这一点:[是test命令的另一种写法,而我们要在test命令后输入空格.

如果我们喜欢将then与if放在同一行,我们必须要加一个冒号来与then进行分隔:

if [ -f fred.c ]; then
...
fi

我们可以用的test命令的条件类型有以下的三种:字符串比较,算术比较和文件条件.下面的三张表展示了这些条件类型:

字符串比较:

string1 = string2    如果相等则为真
string1 != string2    如果不等则为真
-n string        如果不空则为真
-z string        如果为空则为真

算术比较:

expression1 -eq expression2    如果相等则为真
expression1 -ne expression2    如果不等则为真
expression1 -gt expression2    如果大于则为真
expression1 -ge    expression2    大于等于则为真
expression1 -lt expression2    如果小于则为真
expression1 -le expression2    小于等于则为真
!expression            如查为假则为真

文件:

-d file        如果为目录则为真
-e file        如果存在则为真(在这里要注意的是,由于历史原因,-e选项并不可移植,所以常用的是-f选项
-f file        如果为常规文件则为真
-g file        如果设置了组ID则为真
-r file        如果文件可读则为真
-s file        如果文件大小不为零则为真
-u file        如果设置了用户ID则为真
-w file        如果文件可写则为真
-x file        如果文件可执行则为真

现在我们似乎走得有一点的太前了,但是接下来的是一个例子.在这里我们要测试文件/usr/bash,这样我们就可以清楚的看到这些条件的用法:

#!/bin/sh
if [ -f /bin/bash ]
then
   echo “file /bin/bash exists”
fi
if [ -d /bin/bash ]
then
   echo “/bin/bash is a directory”
else
   echo “/bin/bash is NOT a directory”
fi

在测试为真以前,所有的文件测试条件要法度文件存在.这个列表包含了test命令常用的选项,所以我们可查看手册页得到一个完全的信息.如果我们正在使用bash,而其中内嵌了test,我们可以用命令help test得到详细的信息.

原文地址:https://blog.csdn.net/dragonfly0939

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


文章浏览阅读1.8k次,点赞63次,收藏54次。Linux下的目录权限!!!粘滞位!!!超详解!!!
文章浏览阅读1.6k次,点赞44次,收藏38次。关于Qt的安装、Windows、Linux、MacBook_mack book 安装qt
本文介绍了使用shell脚本编写一个 Hello
文章浏览阅读1.5k次,点赞37次,收藏43次。【Linux】初识Linux——了解操作系统的发展历史以及初次体验Linux编程环境
文章浏览阅读3k次,点赞34次,收藏156次。Linux超详细笔记,个人学习时很认真的记录的,觉得好的麻烦点个赞。
文章浏览阅读6.8k次,点赞109次,收藏114次。【Linux】 OpenSSH_9.3p1 升级到 OpenSSH_9.5p1(亲测无问题,建议收藏)_openssh_9.5p1
文章浏览阅读3.5k次,点赞93次,收藏78次。初识Linux中的线程,理解线程的各种概念,理解进程地址空间中的页表转换,介绍pthread线程库并理解线程库!
文章浏览阅读863次。出现此问题为Linux文件权限问题,解决方案为回到引擎目录执行命令。输入用户密码后运行./UnrealEditor。_increasing per-process limit of core file size to infinity.
文章浏览阅读2.9k次。使用文本编辑器:打开CSV文件,并使用文本编辑器(如Notepad++、Sublime Text、Visual Studio Code等)来查看文件的字符编码格式。通常在编辑器的底部状态栏或设置中可以找到当前编码的显示。请注意,上述方法并非绝对准确,特别是当文件没有明确的编码标识时。因此,如果你发现CSV文件在不同的工具或方法中显示不同的编码格式,可能需要进行进一步的分析和判断,或者尝试使用不同的编码转换方法。该命令将输出文件的MIME类型和编码信息。使用命令行工具:在命令行中,你可以使用。_shell读取csv文件逐行处理
本文介绍了如何在Linux系统中升级gcc版本,以便更好地支持C++11及以上版本的新特性。通过升级gcc,可以提升编译器的功能和性能,获得更好的开发体验。详细的步骤和方法请参考原文链接。
文章浏览阅读4.4k次,点赞6次,收藏19次。Mosquitto是一个开源的MQTT消息代理服务器。MQTT是一个轻量级的、基于发布/订阅模式的消息传输协议。 mosquitto的安装使用比较简单,可以方便的来进行一些测试。_linux mosquitto
文章浏览阅读7.2k次,点赞2次,收藏12次。Linux中,用于根目录下有一个.ssh目录,保存了ssh相关的key和一些记录文件。_~/.ssh/
文章浏览阅读4.5k次,点赞5次,收藏18次。首先需要安装 snmp ,使用下面的命令进行安装安装完毕之后,使用下面的命令查看是否安装成功当命令行显示如图即为安装成功。_snmp工具
文章浏览阅读3.5k次,点赞7次,收藏24次。本地部署和使用llama.cpp进行量化Llama2,linux和Windows平台方案,支持CPU和GPU多版本。_llama cpp gpu
文章浏览阅读1.4k次,点赞46次,收藏44次。在vim中,最为常见的有三种模式,分别是:命令模式(command mode)、插 入模式(Insert mode)和底行模式(last line mode)文件保存或退出,也可以进行文件替换,找字符串,列出行号等操作。在命令模式下,shift+: 即可进入该模 式。在进入vim后,使用 i 进入插入模式,插入模式就是vim的编辑模式,可以在vim中进行内容的编辑和修改。vim的核心模式,使用vim进入文件编辑时的最初模式,在该模式中只能移动光标和使用命令对文件内容进行编辑。
Linux常用命令大全,包括目录操作命令和文件操作命令,以及查看登录用户命令和文件内容查看命令等。
文章浏览阅读1.7k次,点赞57次,收藏50次。Yearning 简单, 高效的MYSQL 审计平台 一款MYSQL SQL语句/查询审计工具,为DBA与开发人员使用.本地部署,注重隐私,简单高效的MYSQL审计平台。下面介绍Linux 简单部署Yearning 并结合cpolar 内网穿透工具实现远程访问,破除访问限制,提高工作效率!!
文章浏览阅读1.9w次,点赞7次,收藏18次。Microsoft Edge是一款现代化的浏览器,它拥有众多功能和强大的性能,为用户带来更加流畅的浏览体验。Edge最近推出了分屏功能,支持一个窗口同时显示两个选项卡,这可以大大提高生产力和多任务处理能力。欢迎大家使用分屏及其他新功能后分享自己的使用心得与建议。首先,使用Microsoft Edge的分屏功能确实能够提高生产力,尤其是在需要同时浏览两个不同网页的情况下。分屏功能使得在一个窗口中同时显示两个选项卡,用户可以在两个网页之间快速切换,而无需打开新的窗口或使用多个浏览器窗口。_edge linux
文章浏览阅读1.8k次,点赞83次,收藏71次。C语言实现倒计时和进度条并进行演示。_linux不换行输出倒计时
文章浏览阅读1.5k次,点赞28次,收藏25次。基于嘉立创泰山派开发板,本机使用VMware+Unbuntu,编译泰山派的Linux SDK。详细教程,0基础小白可操作!内涵大量基础操作和linux基本知识。_立创泰山派sdk编译