“Shell编程”的版本间的差异

来自软件实验室
跳转至: 导航搜索
输出附加重定向
while语句
 
(未显示3个用户的14个中间版本)
第2行: 第2行:
 
shell是一种高级程序设计语言
 
shell是一种高级程序设计语言
 
===shell的特点===
 
===shell的特点===
* 组合命令成为心的命令
+
* 组合命令成为新的命令
 
* 允许灵活使用数据流,提供通配符、输入输出重定向、管道等机制
 
* 允许灵活使用数据流,提供通配符、输入输出重定向、管道等机制
 
* 结构化程序设计
 
* 结构化程序设计
第81行: 第81行:
  
 
=== 输入输出重定向符 ===
 
=== 输入输出重定向符 ===
执行一个shell命令时,自动打开三个标准设备文件:标准输入stdin、标准输出stdout、标注出错stderr
+
执行一个shell命令时,自动打开三个标准设备文件:标准输入stdin、标准输出stdout、标准出错stderr
 +
 
 +
很好的参考资料: http://blog.csdn.net/revilwang/article/details/8374362
  
 
==== 输入重定向符< ====
 
==== 输入重定向符< ====
把标准输入设备重新定向到文件
+
把标准输入设备重新定向到文件,标准用法:
 +
<nowiki>
 +
[n]<file
 +
</nowiki>
 +
 
 +
即,将文件描述字为n的设备重定向到file,如果n省略则默认为标准输入设备(n=0)。
  
 
==== 输出重定向符> ====
 
==== 输出重定向符> ====
把脚本或者程序的执行结果写入指定的文件(重定向到文件)
+
把脚本或者程序的执行结果写入指定的文件(重定向到文件):
 +
<nowiki>
 +
[n]>file
 +
</nowiki>
  
 +
即,将文件描述字为n的设备重定向到file。如果n省略则为标准输出设备(n=1)
 +
 +
例如:
 
  <nowiki>
 
  <nowiki>
 
$ who > who.txt
 
$ who > who.txt
第97行: 第110行:
 
把命令的输出结果追加到指定文件的末尾
 
把命令的输出结果追加到指定文件的末尾
  
==== 与文件描述字有关的重定向 ====
+
==== 标准输出和标准错误重定向 ====
 +
将标准输出和标准错误都重定向的用法是:
 +
<nowiki>
 +
&>file
 +
</nowiki>
 +
 
 +
比如下面的命令序列:
 +
<nowiki>
 +
$ ls &> file
 +
$ cat file
 +
$ mkdir &> file
 +
$ cat file
 +
</nowiki>
 +
 
 +
==== 复制文件描述符 ====
 +
用法:
 +
<nowiki>
 +
[n]>&文件描述符
 +
[n]<&文件描述符
 +
</nowiki>
 +
 
 +
比如:
 +
<nowiki>
 +
$ mkdir > file 2>&1 # mkdir的执行结果(标准输出)重定向到file,并且标准错误也重定向到标准输出
 +
</nowiki>
 +
 
 +
此种用法常见于监控一些定时执行的任务的执行结果和出错信息。
  
 
=== 注释、管道、后台命令符 ===
 
=== 注释、管道、后台命令符 ===
 +
 +
管道的作用:将一个命令的输出作为另外一个命令的输入,比如:
 +
 +
<nowiki>
 +
$ ls -l $HOME| wc -l
 +
$ ls | grep *.c | wc -l
 +
</nowiki>
 +
 +
后台命令符&
  
 
=== 命令执行操作符 ===
 
=== 命令执行操作符 ===
 +
==== 顺序执行 ====
 +
逗号隔开多个命令即为顺序执行,比如:
 +
<nowiki>
 +
pwd;who | wc -l;cd /usr/bin
 +
</nowiki>
  
=== 成组命令 ===
+
==== 逻辑与 ====
 +
使用&&连接多个命令,从左向右顺序执行命令,如果遇到一个命令执行不成功,则后面的命令不再执行。比如:
 +
<nowiki>
 +
$ cp test1.c test1.c.bak && rm test1.c
 +
</nowiki>
 +
 
 +
==== 逻辑或 ====
 +
使用||连接多个命令,从左向右顺序执行命令,如果前面的命令执行不成功,则执行后面的命令。也就是说,如果前面的命令执行成功,则后面的命令不再执行。比如:
 +
<nowiki>
 +
$ cat abc || pwd
 +
</nowiki>
  
 
== shell变量 ==
 
== shell变量 ==
 +
和C语言比较一下,shell变量没有类型,不需要预先定义。
 +
 +
* 环境变量:其值不会随脚本执行结束而消失。
 +
* 临时变量:作用范围限于脚本内部。
 +
 +
=== 环境变量 ===
 +
==== 常见环境变量 ====
 +
HOME/MAIL/PATH/PS1/PWD/SHELL/TERM
 +
 +
删除环境变量:unset
 +
==== export的作用 ====
 +
父进程中定义的变量对其子进程的运行环境没有任何影响,只有通过export输出环境变量,子进程才能够访问。
 +
 +
通过两种方式验证:
 +
 +
* 在终端定义变量并输出,然后在shell文件中访问变量(有效)
 +
* 在shell中定义变量并输出,然后在终端访问(无效)
 +
 +
=== 用户定义的变量 ===
 +
* 变量名
 +
* 变量赋值
 +
* 变量的引用:只有这个时候需要$,如果在其他字符串中间,需要{}括起来,比如:${dir}devel
 +
 +
=== 数组 ===
 +
* 数组定义
 +
* 数组元素的引用:${数组名[下标]},$数组名:引用第一个元素(下标为0),下标为*或者@表示用用所有元素,unset 数组名表示取消整个数组的定义
 +
 +
=== 变量引用 ===
 +
归纳一下,变量应用的几种形式:
 +
* $name
 +
* ${name}
 +
* ${name[n]}
 +
* ${name[*]}
 +
* ${name[@]}
 +
* ${name:+word}:如果$name为空,则$name,${name:+word}均为空,否则${name:+word}=word
 +
* ${name:-word}:如果$name为空,则${name:-word}=word,否则${name:-word}值为$name
 +
* ${name:=word}:如果$name为空,则$name=word,${name:=word}=word
 +
* ${name:?word}:如果$name为空,则${name}的值为:shell脚本名:name:word,否则${name:?word}的值为$name
 +
* ${name#pattern}
 +
* ${name##pattern}
 +
* ${name%pattern}
 +
* ${name%%pattern}
 +
* ${#@}
 +
* ${$#*}
 +
* ${#name}
 +
* ${#name[*]}
 +
* ${#name[@]}
 +
 +
=== 输入输出命令 ===
 +
* read输入,简单直观
 +
* echo输出
 +
 +
=== 位置参数 ===
 +
* 0,1,2...是位置变量的名字,因此$0,$1...是对位置变量的引用
 +
* set命令可以为位置变量赋值,除$0外
 +
* $#:参数个数,可以认为,#,?,$等都是特殊变量的名字
 +
* $?:上一条命令的返回值
 +
* $$:当前进程的进程号,通常用于创建临时文件
 +
* $!:上一个后台命令的进程号
 +
* $-:当前shell的执行标志组成的字符串
 +
* $*:命令行所有参数的字符串
 +
* $@:几乎等价于$*,区别类似于${name[*]}和${name[@]}
  
 
== shell控制结构 ==
 
== shell控制结构 ==
第113行: 第238行:
 
=== 条件测试 ===
 
=== 条件测试 ===
  
=== while语句 ===
+
[ $a = "b" ]
 +
 
 +
有两点必须注意:
 +
 
 +
* []内部两端必须有空格
 +
* =两侧必须有空格
 +
 
 +
这两个规定的原因是,如果没有空格,shell会将关系表达式理解为一个字符串。
 +
 
 +
=== 循环控制 ===
 +
 
 +
单行执行shell的一个问题:http://dz.sdut.edu.cn/blog/subaochen/?p=638
  
 
== shell函数 ==
 
== shell函数 ==

2015年12月18日 (五) 13:55的最新版本

shell概述

shell是一种高级程序设计语言

shell的特点

  • 组合命令成为新的命令
  • 允许灵活使用数据流,提供通配符、输入输出重定向、管道等机制
  • 结构化程序设计
  • 提供可配置的环境

shell的主要版本

csh/ksh/bash/ash/zsh,主流:bash

基本的bash shell脚本示例

#!/bin/bash
# very simple bash script
date
pwd
cd

shell脚本的文件扩展名通常为.sh,并具有可执行权限。

其中#!/bin/bash是必须的,表示调用/bin/bash解释下面的shell命令。

其中#开头的行为注释

shell脚本的执行

  • sh ./test.sh
  • chmod +x ./test.sh; ./test.sh

shell中的特殊字符

通配符

  • *,圆点和路径符号必须显式匹配
  •  ?
  • [字符组],比如f[abcd]匹配fa,fb,fc,fd,f[a-d],f[1-9]
  •  !,比如f[!1-9]

模式表达式

可以包含多个通配符,并支持扩展模式匹配:

  • *(模式表),比如file*(.c|.o)匹配file,file.c,file.c.c,file.c.o,file.o.c,file.o.o等,不匹配file.h
  • +(模式表),比如file+(.c|.o)匹配file.c,file.o,file.c.o,file.c.c等,但是不匹配file
  •  ?(模式表),file?(.c|.o)匹配file,file.c,file.o,不匹配file.c.o
  • @(模式表),file@(.c|.o)匹配file.c,file.o,不匹配file,file.c.c等
  •  !(模式表),file!(.c|.o)匹配file,file.a,不匹配file.c,file.o

引号

双引号

由双引号括起来的字符均作为普通字符对待,$,`,\三个字符除外:

  • $表示变量替换
  • `表示命令替换
  • \表示转义字符,通常用于显示特殊字符$\."'等,比如:echo "filename is \"$HOME\"\$*"的结果是:filename is "/home/subaochen"$*

需要注意的是:双引号中的单引号是普通字符

例子:

echo "current directory is `pwd`"
echo "home directory is $HOME"
echo "file*.?"
echo "directory '$HOME'"

单引号

单引号括起来的字符都是普通字符,不进行变量替换和命令替换,比如:

echo 'home directory is $HOME'

并不进行变量替换。同理也适应于命令替换。

倒引号

命令替换,比如:

echo `pwd`
echo `date`

输入输出重定向符

执行一个shell命令时,自动打开三个标准设备文件:标准输入stdin、标准输出stdout、标准出错stderr

很好的参考资料: http://blog.csdn.net/revilwang/article/details/8374362

输入重定向符<

把标准输入设备重新定向到文件,标准用法:

[n]<file

即,将文件描述字为n的设备重定向到file,如果n省略则默认为标准输入设备(n=0)。

输出重定向符>

把脚本或者程序的执行结果写入指定的文件(重定向到文件):

[n]>file

即,将文件描述字为n的设备重定向到file。如果n省略则为标准输出设备(n=1)

例如:

$ who > who.txt
$ cat who.txt

输出附加重定向>>

把命令的输出结果追加到指定文件的末尾

标准输出和标准错误重定向

将标准输出和标准错误都重定向的用法是:

&>file

比如下面的命令序列:

$ ls &> file
$ cat file
$ mkdir &> file
$ cat file

复制文件描述符

用法:

[n]>&文件描述符
[n]<&文件描述符

比如:

$ mkdir > file 2>&1 # mkdir的执行结果(标准输出)重定向到file,并且标准错误也重定向到标准输出

此种用法常见于监控一些定时执行的任务的执行结果和出错信息。

注释、管道、后台命令符

管道的作用:将一个命令的输出作为另外一个命令的输入,比如:

$ ls -l $HOME| wc -l
$ ls | grep *.c | wc -l

后台命令符&

命令执行操作符

顺序执行

逗号隔开多个命令即为顺序执行,比如:

pwd;who | wc -l;cd /usr/bin

逻辑与

使用&&连接多个命令,从左向右顺序执行命令,如果遇到一个命令执行不成功,则后面的命令不再执行。比如:

$ cp test1.c test1.c.bak && rm test1.c

逻辑或

使用||连接多个命令,从左向右顺序执行命令,如果前面的命令执行不成功,则执行后面的命令。也就是说,如果前面的命令执行成功,则后面的命令不再执行。比如:

$ cat abc || pwd

shell变量

和C语言比较一下,shell变量没有类型,不需要预先定义。

  • 环境变量:其值不会随脚本执行结束而消失。
  • 临时变量:作用范围限于脚本内部。

环境变量

常见环境变量

HOME/MAIL/PATH/PS1/PWD/SHELL/TERM

删除环境变量:unset

export的作用

父进程中定义的变量对其子进程的运行环境没有任何影响,只有通过export输出环境变量,子进程才能够访问。

通过两种方式验证:

  • 在终端定义变量并输出,然后在shell文件中访问变量(有效)
  • 在shell中定义变量并输出,然后在终端访问(无效)

用户定义的变量

  • 变量名
  • 变量赋值
  • 变量的引用:只有这个时候需要$,如果在其他字符串中间,需要{}括起来,比如:${dir}devel

数组

  • 数组定义
  • 数组元素的引用:${数组名[下标]},$数组名:引用第一个元素(下标为0),下标为*或者@表示用用所有元素,unset 数组名表示取消整个数组的定义

变量引用

归纳一下,变量应用的几种形式:

  • $name
  • ${name}
  • ${name[n]}
  • ${name[*]}
  • ${name[@]}
  • ${name:+word}:如果$name为空,则$name,${name:+word}均为空,否则${name:+word}=word
  • ${name:-word}:如果$name为空,则${name:-word}=word,否则${name:-word}值为$name
  • ${name:=word}:如果$name为空,则$name=word,${name:=word}=word
  • ${name:?word}:如果$name为空,则${name}的值为:shell脚本名:name:word,否则${name:?word}的值为$name
  • ${name#pattern}
  • ${name##pattern}
  • ${name%pattern}
  • ${name%%pattern}
  • ${#@}
  • ${$#*}
  • ${#name}
  • ${#name[*]}
  • ${#name[@]}

输入输出命令

  • read输入,简单直观
  • echo输出

位置参数

  • 0,1,2...是位置变量的名字,因此$0,$1...是对位置变量的引用
  • set命令可以为位置变量赋值,除$0外
  • $#:参数个数,可以认为,#,?,$等都是特殊变量的名字
  • $?:上一条命令的返回值
  • $$:当前进程的进程号,通常用于创建临时文件
  • $!:上一个后台命令的进程号
  • $-:当前shell的执行标志组成的字符串
  • $*:命令行所有参数的字符串
  • $@:几乎等价于$*,区别类似于${name[*]}和${name[@]}

shell控制结构

if语句

条件测试

[ $a = "b" ]

有两点必须注意:

  • []内部两端必须有空格
  • =两侧必须有空格

这两个规定的原因是,如果没有空格,shell会将关系表达式理解为一个字符串。

循环控制

单行执行shell的一个问题:http://dz.sdut.edu.cn/blog/subaochen/?p=638

shell函数

作业控制

shell内置命令

shell脚本调试技术