Linux中Shell入门教程

Shell入门教程:Shell变量   

变量

变量是暂时用来存储数据的地方,是一个内存空间。bash shell和其他的编程语言,没有“数据形态”,也就是说默认情况下不区分一个变量是整型还是浮点型等,除非你使用declare语句申明变量类型。在bash shell中,默认只有一种数据型,就是由字符组成的字符串。同时,设定的变量只在当前的shell中存在,也就是,每一个shell都会维护一份他们自己的变量,彼此不会有影响。可以把变量导出成环境变量,这样其他的shell就可以被子shell引用。

变量的命名规则:

1.可以使用英文字母、数字和下划线组成

2.第一个字符不能是数字

3.区分大小写

变量设定:

变量名=值

例如:name=john

建议这样设定变量:name="john" 或者name='john'

在引用变量的时候使用双引号和单引号是有区别的,单引号不会进行变量替换。而在双引号中,如果也想抑制变量替换,则需要使用转义符反斜线

引用变量:

$变量名

建议这样引用变量:${变量名}

环境变量:

使用下面的任意一个方法可以使name变为环境变量

name="john"
export name
export name="john"
declare -x name="john"
bash的一些重要的内置变量:

$1 ~ $n?   参数位置。当n超过9后,使用${n},例如${10}
$*   代表所有的参数位置,而且视为一个字符串
$@   代表所有的参数位置,但是代表各位置参数组成的串行
$#    参数的个数
$?    上一个命令的返回值
$!    上一个后台进程的编号
$$   目前shell的进程编号
 

Shell的基本结构 

shell程序的基本组成结构

shell结构大体是由设定变量、内置命令、shell的语法结构、函数组成。

使用实例说明:test.sh

 代码如下 复制代码

#!/bin/bash
#说明使用/bin/bash作为这个脚本的解释器
#定义一个函数
function my_fun () {
 echo "Hello, $1,today is $2"
}
#定义连个变量
name=$1
today=`date`
#函数调用
my_fun "$name" "$today"

上面的这个脚本要想运行还需要做一些操作,首先给予执行权限

chmod +x test.sh
然后执行

./test.sh john
输出

Hello, john,today is Tue Jun? 1 14:51:46 CST 2010
父shell和子shell

在执行script之前,身处的环境就是父shell。执行script之时,父shell根据#!/bin/bash,fork出来一个新的shell环境,然后在子shell中执行,执行完毕后子shell结束,任然回到父shell中,这样不会影响到父shell的环境。
 

这张图片是login shell的流程,当是non-login shell时,只执行方框中的标注的部分。由这张图我们可以知道,在如下几种情况下,执行的流程。

登陆(login)

/etc/profile
~/.bash_profile
注销(logout)

~/.bash_logout
执行新shell,分成两种情况

1.执行交互式的shell

~/.bashrc
/etc/bashrc
2.执行非交互式的shell,比如执行script会检查 BASH_ENV 变量的内容,如果有定义,则执行。

Shell函数的返回值   

shell函数返回值一般有3种方式:

1、return语句(默认的返回值)

shell函数的返回值可以和其他语言的返回值一样,通过return语句返回。

比如:

 代码如下 复制代码

#!/bin/bash
function mytest() {
 
 echo "mytest function"
 echo "argv[1] = $1"

 if [ $1 = "1" ] ;then
  return 1
 else
  return 0
 fi

}

echo "mytest 1"
mytest 1
echo $?

echo "mytest 0"
mytest 0
echo $?

if mytest 1 ; then
 echo "mytest 1"
fi

if mytest 0 ;then
 echo "mytest 0"
fi

echo "end"

先定义了一个函数,mytest,它根据输入的参数是否为1来return 1,否则return 0。

获取函数的返回值通过调用函数,或者最后执行的值获得。

另外,可以直接用函数的返回值用作if的判断。

注意:return只能用来返回整数值,且和c的区别是返回为正确,其他的值为错误。

2、全局变量或者环境变量

这种就类似于c中的全局变量。

 代码如下 复制代码

#!/bin/bash

g_var=

function mytest2() {
 echo "mytest2"
 echo "args $1"
 g_var=$1
 return 0
}

mytest2 1

echo "g_var=$g_var"

函数mytest2通过修改全局变量的值来返回结果。

3、以上两个方法失效的时候

以上介绍的这两种方法在一般情况下都是好使的,但也有例外。

比如:

 代码如下 复制代码

#!/bin/bash

function mytest3() {
 grep "123" test.txt | awk -F: '{print $2}' | while read line ;do
 echo "$line"
 if [ $line = "yxb" ]; then
  return 0
 fi
 done
 echo "mytest3 here "
 return 1
}

g_var=

function mytest4() {
 grep "123" test.txt | awk -F: '{print $2}' | while read line ;do
 echo "$line"
 if [ $line = "yxb" ]; then
  g_var=0
  echo "g_var=0"
  return 0
 fi
 done
 echo "mytest4 here "
 return 1
}

mytest3
echo $?

mytest4
echo "g_var=$g_var"

test.txt中的内容如下:

 代码如下 复制代码

456:kkk
123:yxb
123:test

输出如下:

yxb@yxb-laptop:~/文档/个人文档/shell函数返回值$ ./no_function.sh
yxb
mytest3 here
1
yxb
g_var=0
mytest4 here
g_var=

可以看到mytest3在return了以后其实没有直接返回,而是执行了循环体后的语句,同时看到mytest4中也是一样,同时,在mytest4中,对全局变量的修改也无济于事,全局变量的值根本就没有改变。

这个是什么原因那?

笔者认为,之所以return语句没有直接返回,是因为return语句是在管道中执行的,管道其实是另一个子进程,而return只是从子进程中返回而已,只是while语句结束了,而函数体之后的语句会继续执行。

同理,全局变量在子进程中进行了修改,但是子进程的修改没有办法反应到父进程中,全局变量只是作为一个环境变量传入子进程,子进程修改自己的环境变量,不会影响到父进程。

因此在写shell函数的时候,用到管道的时候一定要清楚,此刻是从什么地方返回。

4、echo返回值(显式输出)

其实在shell中,函数的返回值有一个非常安全的返回方式,即通过输出到标准输出返回。因为子进程会继承父进程的标准输出,因此,子进程的输出也就直接反应到父进程。因此不存在上面提到的由于管道导致返回值失效的情况。

在外边只需要获取函数的返回值即可。

 代码如下 复制代码

#!/bin/bash

function mytest5() {
 grep "123" test.txt | awk -F: '{print $2}' | while read line ;do
 if [ $line = "yxb" ]; then
  echo "0"
  return 0
 fi
 done
 return 1
}

result=$(mytest5)

if [ -z $result ]; then
 echo "no yxb. result is empyt"
else
 echo "have yxb, result is $result"
fi

输出如下:

view sourceprint?
1 have yxb, result is 0
这个方式虽然好使,但是有一点一定要注意,不能向标准输出一些不是结果的东西,比如调试信息,这些信息可以重定向到一个文件中解决,特别要注意的是,用到比如grep这样的命令的时候,一定要记得 1>/dev/null 2>&1 来避免这些命令的输出。

echo输出另一技巧:用函数的返回值作为另外一个函数的参数

 代码如下 复制代码

#!/bin/bash
Dir=/cygdrive/d/server/ebin
function display() {
 files=`ls $Dir`
 echo $files
}
echo `display`
 
function filetype() {
    echo `file $Dir/$1`  #输出待检测文件的类型
}
 
for file in `display`    #调用display函数,对其返回值做遍历
do
    filetype $file       #检测文件类型并输出
done

小总结:

用 $? 来获取函数的 return值,用 $(函数名) 来获取函数的 echo值。

Shell函数详解  

 

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

1、函数定义

function 函数名() {
 语句
 [return]
}

关键字function表示定义一个函数,可以省略,其后是函数名,有时函数名后可以跟一个括号,符号“{”表示函数执行命令的入口,该符号也可以在函数名那一行,“}”表示函数体的结束,两个大括号之间是函数体。

语句部分可以是任意的Shell命令,也可以调用其他的函数。

如果在函数中使用exit命令,可以退出整个脚本,通常情况,函数结束之后会返回调用函数的部分继续执行。

可以使用break语句来中断函数的执行。

declare –f 可以显示定义的函数清单

declare –F 可以只显示定义的函数名

unset –f 可以从Shell内存中删除函数

export –f 将函数输出给Shell

另外,函数的定义可以放到 .bash_profile 文件中,也可以放到使用函数的脚本中,还可以直接放到命令行中,还可以使用内部的unset命令删除函数。一旦用户注销,Shell将不再保持这些函数。

2、函数的调用

函数调用的实例:

 代码如下 复制代码

#!/bin/bash
function show() {
 echo "hello , you are calling the function"
}
echo "first time call the function"
show
echo "second time call the function"
show

3、函数参数的传递

函数可以通过位置变量传递参数。例如

函数名 参数1 参数2 参数3 参数4

当函数执行时,$1 对应 参数1,其他依次类推。

实例:

 代码如下 复制代码

#!/bin/bash
function show() {
 echo "hello , you are calling the function  $1"
}
echo "first time call the function"
show first
echo "second time call the function"
show second

4、函数的返回值

函数中的关键字“return”可以放到函数体的任意位置,通常用于返回某些值,Shell在执行到return之后,就停止往下执行,返回到主程序的调用行,return的返回值只能是0~256之间的一个整数,返回值将保存到变量“$?”中。

实例:

 代码如下 复制代码
#!/bin/bash
function abc() {
 RESULT=`expr $1 % 2`   #表示取余数
 if [ $RESULT –ne 0 ] ; then
  return 0
 else
  return 1
 fi
}
echo "Please enter a number who can devide by 2"
read N
abc $N
case $? in
 0)
  echo "yes ,it is”
  ;;
 1)
  echo “no ,it isn’t”
  ;;
esac

在这里要注意参数传递了,上面read进来的数字,必须加上$符号才能传递给函数,我刚开始不知道是哪里错了,找了半天才知道是这里出错了。

5、函数的载入

如果函数在另外一个文件中,我们该怎么调用它呢?

这里就有一个方法。比如 show 函数写在了function.sh里面了,我们就可以用

 代码如下 复制代码

source function.sh 

2 show

这样就可以调用了。

6、函数的删除

用法:unset –f 函数名

7、函数的变量作用域

默认情况下,变量具有全局作用域,如果想把它设置为局部作用域,可以在其前加入local

例如:

 代码如下 复制代码

 local a="hello"

使用局部变量,使得函数在执行完毕后,自动释放变量所占用的内存空间,从而减少系统资源的消耗,在运行大型的程序时,定义和使用局部变量尤为重要。

8、函数的嵌套

函数可以进行嵌套,实例:

 代码如下 复制代码

#!/bin/bash
function first() {
 function second() {
  function third() {
   echo "------this is third"
  }
  echo "this is the second"
  third
 }
 echo "this is the first"
 second
}

echo "start..."
first

 
Shell当中的特殊变量   

一、保留变量

$IFS 这个变量中保存了用于分割输入参数的分割字符,默认识空格。

$HOME 这个变量中存储了当前用户的根目录路径。

$PATH 这个变量中存储了当前 Shell 的默认路径字符串。

$PS1 表示第一个系统提示符。

$PS2 表示的二个系统提示符。

$PWD 表示当前工作路径。

$EDITOR 表示系统的默认编辑器名称。

$BASH 表示当前 Shell 的路径字符串。

$0, $1, $2, ...

表示系统传给脚本程序或脚本程序传给函数的第0个、第一个、第二个等参数。

$# 表示脚本程序的命令参数个数或函数的参数个数。

$$ 表示该脚本程序的进程号,常用于生成文件名唯一的临时文件。

$? 表示脚本程序或函数的返回状态值,正常为 0,否则为非零的错误号。

$* 表示所有的脚本参数或函数参数。

$@ 和 $* 涵义相似,但是比 $* 更安全。

$! 表示最近一个在后台运行的进程的进程号。

二、随机数

随机数是经常要用到的,BASH 中也提供了这个功能,请看下面这个程序:

 代码如下 复制代码

#!/bin/bash
# Prints different random integer from 1 to 65536
a=$RANDOM
echo $a
exit 0

这个程序可以在每次执行的时候随机的打印出一个大小在 1 到 65536 之间的整数。

时间: 2024-09-20 09:15:07

Linux中Shell入门教程的相关文章

应用-Linux中shell脚本问题

问题描述 Linux中shell脚本问题 ]我有shell脚本,放在/bin/目录下,内容如下: #!/bin/sh cd /usr /sbin/insmod s3c_ts.ko ./digitpic ./MSYH.TTF & 当我开发板上电以后我手动执行手动执行test.sh 我的digitpic应用程序能够正常启动 当我在/etc/init.d/rcS 文本里面最后添加exec test.sh 提示说这个触摸屏读取错误,也就是/sbin/insmod s3c_ts.ko这部分错误了,就只有触

linux中shell变量$#,$@,$0,$1,$2的含义解释

比如脚本名称叫start.sh 输入参数三个: 1 2 3 运行test.sh 1 2 3后 $*为"1 2 3"(一起被引号包住) $@为"1" "2" "3"(分别被包住) $#为3(参数数量) linux中shell变量$#,$@,$0,$1,$2的含义解释:  变量说明:  $$  Shell本身的PID(ProcessID)  $!  Shell最后运行的后台Process的PID  $?  最后运行的命令的结束代码

linux中shell脚本实现下载完关机_linux shell

用mint 有一段时间了,下载基本用firefox,有时下载几个G的游戏.可是firefox没有找到下载完关机的选择.处于这个原因,写了这个. download_shutdown.sh #!/bin/bash # Created By: Demo <demo@demo.com> # Created Time: 2015-01-30 12:36:44 # Modified Time: 2015-01-30 12:54:21 dir=$1 while [ "1" ] do if

linux中Shell命令用法入门教程

什么时候使用Shell 因为Shell似乎是各UNIX系统之间通用的功能,并且经过了POSIX的标准化.因此,Shell脚本只要"用心写"一次,即可应用到很多系统上.因此,之所以要使用Shell脚本是基于:     简单性:Shell是一个高级语言:通过它,你可以简洁地表达复杂的操作.     可移植性:使用POSIX所定义的功能,可以做到脚本无须修改就可在不同的系统上执行.     开发容易:可以在短时间内完成一个功能强大又妤用的脚本. 但是,考虑到Shell脚本的命令限制和效率问题

Linux系统中git 入门教程

  Git 起源 同生活中的许多伟大事件一样,Git 诞生于一个极富纷争大举创新的年代.Linux 内核开源项目有着为数众广的参与者.绝大多数的 Linux 内核维护工作都花在了提交补丁和保存归档的繁琐事务上(1991-2002年间).到 2002 年,整个项目组开始启用分布式版本控制系统 BitKeeper 来管理和维护代码.到了 2005 年,开发 BitKeeper 的商业公司同 Linux 内核开源社区的合作关系结束,他们收回了免费使用 BitKeeper 的权力.这就迫使 Linux

linux中shell脚本数组的操作教程

数组赋值:a=(1 2 3 4 5) a[1]=1 数组长度:echo ${#a[@]} 或者 echo ${#a[*]} 读取数组:echo ${a[@]} 或者 echo ${a[*]} echo ${a[0]}                             PS: 数组下标从0开始 删除数组:unset a unset a[1] 数组分片:echo ${a[@]:0:3}                  显示为1,2,3                ps:截取前3个数组值显示

Linux中Shell变量详解

Shell变量分为环境变量和自定义变量,这两则的差异在于该变量能否被子进程使用,看下面的一个示 意图: 如果是环境变量,子进程中还可以继续使用,但如果是自定义的变量,子进程里将失效. 用env查看环境变量 常见的环境变量如下: 1)HOME:用户的主目录(cd ~) 2)SHELL:用户的默认shell 3)HISTSIZE:历史记录条数 4)MAIL:邮件信箱文件 5)PATH:执行文件查找路径 6)LANG:语系 用set查看环境变量和自定义变量 比较重要的自定义变量有: 1)PS1:提示符

linux中shell命令test用法和举例

test 命令期望在命令行中找到一个参数,当 shell 没有为变量赋值时,则将该变量视为空.这意味着在处理脚本时,一旦脚本寻找的参数不存在,则 test 将报告该错误. 当试图保护脚本时,您可以通过将所有参数包含在双引号中来解决这个问题.然后 shell 将变量展开,如果变量没有值,那么将传递一个空值给 test.另一种方法是在脚本内增加一个额外检查过程来判断是否设置了命令行参数.如果没有设置命令行参数,那么脚本会告诉用户缺少参数,然后退出.我们会通过一些例子来更具体地说明所有这些内容. te

linux中shell脚本进行MySQL数据库定时备份

具体方法  代码如下 复制代码 #!/bin/bash #Shell Command For Backup MySQL Database Everyday Automatically By Crontab #Author : Carlos Wong #Date : 2010-08-24 #配置参数  代码如下 复制代码 USER=root #数据库用户名" >用户名 PASSWORD=××××× #数据库用户密码 DATABASE=TIENIUZAI    #数据库名称 WEBMASTER