第二章 Shell程序设计

四、管道和重定向

1 重定向输出

ls -l > lsoutput.txt

ps >> lsoutput.txt  >>表示附加到一个文件中

文件描述符0:标准输入

文件描述符1:标准输出

文件描述符2:标准错误输出

kill -HUP 1234 >killout.txt 2>killerr.txt   标准输出重定向到killout.txt中了;标准错误输出(文件描述符2)重定向到killerr.txt中了

kill -l 1234 > killouterr.txt 2>&1  把两组输出都重定向到一个文件中了,使用>&来结合的,注意2和1的出现顺序!此处表示“将标准输出(1)重定向到killouterr.txt中,然后再将标准错误(2)输出到与标准输出相同的地方”

2 管道

可使用管道操作符|来连接进程

如离散命令:

  ps > psout.txt

  sort psout.txt > pssort.out

可以直接写为:

  ps | sort > pssort.out

五、shell可以作为程序设计语言

交互式程序 + 创建创建脚本 两种方式写shell程序

1 交互式

  ls my_{finger,toe}s    列出文件my_fingers和my_toes

  grep -l POSIX * | more

2 创建脚本

例子:创建一个名为fisrt的shell脚本,完成的功能是:所有当前目录下内容包含“apple”字符串的文件,并打印出文件名字

#! /bin/sh   #是一种特殊形式的注释,告知系统/bin/sh就是用来执行本文件的程序

for file in *
do
if grep -q apple $file
then
echo $file
fi
done exit

有两种执行方式:

方式1: $/bin/sh first  明确指出运行shell脚本的程序

方式2:  

  $chmod +x first

  $./first

六、shell的语法

1 变量

无需事先声明,通过加$符来访问变量的内容,默认所有变量都被看作字符串并以字符串来存储

#a=7+5

#echo $a

7+5

read命令可以将用户输入的值读给一个变量:

#read var

hello world

#echo $var

hello world

关于变量中引号的使用:包括双引号、单引号 和 \字符:

#!/bin/sh

myvar="Hi there"

echo $myvar
echo "$myvar"
echo '$myvar'
echo \$myvar

输出如下:

  Hi there

  Hi there

  $myvar

  $myvar

环境变量(名字通常全大写):

  $HOME

  $PATH

  $PS1   命令提示符,通常是$

  $PS2   二级提示符,用来提示后续到输入,通常是>

  $IFS   输入域分割符。通常是空格、制表符、换行符

  $0    SHELL脚本的名字

  $#     传递给脚本的参数个数

  $$    SHELL脚本的进程号

参数变量:

  $1, $2, ...   脚本程序的参数

  $*      在一个变量中列出所有的参数,各个参数之间用环境变量IFS中到第一个字符分割开

  $@      是$*的一种精巧的变体,它不使用IFS环境变量,所以即使IFS为空,参数也不会挤在一起

例子:展示$@ 和 $*的区别

$ IFS=''

$ set foo bar bam

$ echo "$@"

foo bar bam

$ echo "$*"

foobarbam

$ unset IFS

$ echo "$@"

foo bar bam      不使用IFS环境变量,所以即使IFS为空,参数也不会挤在一起

使用参数和环境变量的例子:

#!/bin/sh

echo "The program $0 is now running"
echo "The second parameter was $2"
echo "The first parameter was $1"
echo "The parameter list was $*" exit

运行该脚本

$ ./test foo bar baz

The program ./test is now running

The second parameter was bar

The first parameter was foo

The parameter list was foo bar baz

2 条件

条件测试使用test或者[]命令:

  if test -f fred.c    #-f 表示测试一个文件是否存在

  then

    ...

  fi

等价于:

  if [ -f fred.c ]

  then

    ...

  fi

举例:

#!/bin/sh

echo "The program $0 is now running"

if [ -f /bin/bash ]; then
#statements
echo "file /bin/bash exists"
fi if [ -d /bin/bash ]; then
#statements
echo "/bin/bash is a directory"
else
echo "/bin/bash is Not a directory"
fi exit

3 控制结构

(1)if语句

if condition

then

  ...

else

  ...

fi

(2)elif语句

if condition

then  

  ...

elif condition

  ...

else

  ...

fi

(2)for语句

for variable in values

do

  ...

done

实验1:

#! /bin/sh

for foo in bar fud
do
echo $foo
done exit

输出:

  bar

  fud

  43

(3)while语句

while condition

do

  ...

done

(4)until语句

until condition

do

  ...

done

注:while是条件成立往下走,而until相反!

(5)case语句

case variable in

  pattern [ | pattern ] ...) statement;;

  pattern [ | pattern ] ...) statement;;

esac

case实例1:用户输入

#! /bin/sh

echo "Is it morning? Please answer yes or no"
read timeofday case "$timeofday" in
yes ) echo "Good Morning";;
no ) echo "Good Afternoon";;
y ) echo "Good Morning";;
n ) echo "Good Afternoon";;
* ) echo "Sorry, answer not recognized";;
esac exit

case实例2:合并匹配模式

#! /bin/sh

echo "Is it morning? Please answer yes or no"
read timeofday case "$timeofday" in
yes | y | Yes | YES ) echo "good morning";;
n* | N* ) echo "good afternoon";;
* ) echo "sorry";;
esac exit

case实例3:执行多条语句

#! /bin/sh

echo "Is it morning? Please answer yes or no"
read timeofday case "$timeofday" in
yes | y | Yes | YES )
echo "good morning"
echo "up bright and early this morning"
;;
[nN]* )
echo "good afternoon"
;;
* )
echo "sorry"
echo "bad input"
;;
esac exit

(6)命令列表

AND列表

  statement1 && statement2 && statement3 && ...

  只有在前面所有命令都执行成功的情况下才执行后一条语句

OR列表

  statement1 || statement2 || statement3 || ...

   只要有一条命令执行成功,后面的命令将不再执行!

(7)语句块

  想在某些只允许使用单个语句的地方(如在AND或OR列表中)使用多条语句,就可以使用{}来构造一个语句块

(8)一个与变量有关的问题

例子:

  if [ $timeofday = "yes" ]

  then

    echo "good morning"

  ...

  ...

  假如$timeofday为空,则if中的条件变成了:if [ = "yes" ],而这不是一个合法条件,因此程序报错,而应该尽量写成:

  if [ "$timeofday" = "yes" ]   上面的例子中都是这么写的,要注意!!!

4 函数

function_name(){

  statements

}

实例:演示参数传递以及函数返回值

#! /bin/sh

yes_or_no(){

    echo "Is your name $* ?"
while [ true ]; do
echo -n "Enter yes or no: "
read x
case "$x" in
y | yes ) return ;;
n | no ) return ;;
* ) echo "Answer yes or no";;
esac
done
} echo "Original parameters are $*" if yes_or_no "$1"; then
echo "Hi $1, nice name"
else
echo "Never mind"
fi exit

5 命令

(1)break命令  仅在for、while、until中用

(2)命令  空命令,偶尔被用于简化条件逻辑,相当于true的别名

(3) continue命令   仅在for、while、until中用

(4).命令  用于在当前shell中执行命令

(5)echo命令   echo命令默认末尾有换行符,欲去掉可以用 echo -n

(6)eval命令  允许你对参数进行求值

    foo=10

    x=foo

    y='$'$x

    echo $y  此时会输出$foo

    foo=10

    x=foo

    eval y='$'$x

    echo $y  此时会输出10

(7)exec命令

  用法1:典型用法:将当前shell替换为一个不同的程序

    exec wall 'thanks' 脚本中的这个命令会用wall命令替换当前的shell。脚本中exec后面的代码都不会执行,因为执行这个脚本的shell都已经不存在了

  用法2:修改当前文件描述符(很少见)

(8)exit n命令  使脚本以退出码n结束运行

  退出码0表示成功,退出码1~125是脚本程序可用的错误代码,其余数字具有保留含义

(9)export命令  将作为它参数的变量导出到子shell中,并使之在子shell中有效。

  一般,在一个shell中被创建的变量在这个shell调用的子shell中是不可用的。

  

  注:一旦一个变量被shell导出,它就可以被该shell调用的任何脚本使用,也可以被后续依次调用的任何shell使用。本例若export2再调用了另一个脚本,bar的值对新脚本来说仍有效!

(10)expr命令  将其参数当做一个表达式来求值

    x=1

    x=$x+1

    echo $x     会输出1+1,不是我们想要的!

    

    x=1  

    x=`expr $x + 1`  特别注意这里是反引号,而非单引号,键盘上容易打错!

    echo $x    输出2,√

    

    x=1  

    x=$(expr $x + 1)

    echo $x    输出2,√

  

    如今在新脚本程序中,expr被替换为更有效的$((...))语法:

    x=1  

    x=$(($x + 1))

    echo $x      输出2,√

(11)printf命令  格式化输出

    printf "%s %d\t%s" "Hi There" 15 people

(12)return命令

(13)set命令   为shell设置参数变量

    echo the date is $(date)  输出 the date is Sun Dec 13 14:32:28 EST 2015

    set $(date)

    echo the month is $2  输出 the month is Dec

(14)shift命令 把所有参数变量左移一个位置,使$2变为$1,$3变为$2,原来$1的值被丢弃而$0不变  

#! /bin/sh

while [ "$1" != "" ]; do
echo "$1"
shift
done
exit

  若执行 ./test 1 2 3 4 5,则会输出:

  1

  2

  3

  4

  5

(15)trap命令 用于指定在接收到信号后将要采取的行动

  trap -l 查看信号编号及其关联的名称

  trap command signal   #command表示接收到signal信号时将要采取的行动

(16)unset命令 从环境中删除变量和函数。 不常用

(17)find命令(不属于shell)  搜索文件

  find [path] [options] [tests] [actions]

举例:

  find / -name test -print  从根目录/开始搜索名字为test的文件并print出来

  find . -newer while2 -print   在当前目录下搜索比while2要新的文件

  find . -newer while2 -type f -print 在上一个命令的基础上进行约束,使结果仅包含普通文件

  find . \( -name "_*" -or -newer while2 \) -type f -print

(18)grep命令(不属于shell) 通用正则表达式解析器,可使用其在文件中搜索字符串

  grep [options] PATTERN [FILES]

举例:

  grep in words.txt    在words.txt中搜索字符串in

  grep -c in words.txt words2.txt  在两个不同的文件中计算匹配行的数目

  grep -c -v in words.txt words2.txt 使用-v选项进行取反,在两个文件中计算不匹配行的数目

(19)正则表达式

先举几个例子:

  grep e$ words2.txt   查找以e结尾的行

  grep a[[:blank:]] words2.txt  查找以a结尾的单词

  grep Th.[[:space:]] words2.txt  查找以Th开头的由3个字母组成的单词

  grep -E [a-z]\{10\} words2.txt  搜索只有10个字符长的全部由小写字母组成的单词

  

6 命令的执行

(1)算术扩展

  expr命令也可以执行一些算术命令,但慢,因为其需要调用一个新的shell来处理expr命令

  替代办法:$((...))   把准备求值的表达式放在其中

(2)参数扩展

for i in  ; do
my_secret_process $i_tmp 不行,不认识$i_tmp
done

需写成:

  my_secret_process ${i}_tmp

7 here文档

here文档可以在shell脚本中用于向一条命令传递数据:

  cat << !FUNKY!

  hello

  this is a here

  document

  !FUNKY!

输出:

  hello

  this is a here

  document

七、迈向图形化:dialog工具

Linux程序设计 读笔2 Shell脚本的更多相关文章

  1. Linux程序设计 读笔1

    第一章 入门 Linux应用程表现为两种特殊类型文件:可执行文件 + 脚本文件 /bin 二进制文件目录,存放启动系统时用到的标准程序 /usr/bin 用户二进制文件目录,存放用户使用的标准程序 / ...

  2. Linux程序设计 读笔3 文件操作

    一 linux文件结构 二 系统调用和设备驱动程序 三 库函数 四 底层文件访问 五 标准IO库 六 格式化输入输出 七 文件和目录的维护 八 扫描目录 九 错误处理 十

  3. linux c程序中获取shell脚本输出的实现方法

    linux c程序中获取shell脚本输出的实现方法 1. 前言Unix界有一句名言:“一行shell脚本胜过万行C程序”,虽然这句话有些夸张,但不可否认的是,借助脚本确实能够极大的简化一些编程工作. ...

  4. Linux自动安装JDK的shell脚本

    Linux自动安装JDK的shell脚本 A:本脚本运行的机器,Linux B:待安装JDK的机器, Linux 首先在脚本运行的机器A上确定可以ssh无密码登录到待安装jdk的机器B上,然后就可以在 ...

  5. Linux学习Day6:编写Shell脚本

    Shell脚本命令的工作方式有两种: 交互式(Interactive):用户每输入一条命令就立即执行. 批处理(Batch):由用户事先编写好一个完整的Shell脚本,Shell会一次性执行脚本中诸多 ...

  6. linux 的基本操作(编写shell 脚本)

    终于到shell 脚本这章了,在以前笔者卖了好多关子说shell脚本怎么怎么重要,确实shell脚本在linux系统管理员的运维工作中非常非常重要.下面笔者就带你正式进入shell脚本的世界吧. 到现 ...

  7. 一个简单的linux下设置定时执行shell脚本的示例

    很多时候我们有希望服务器定时去运行一个脚本来触发一个操作,比如说定时去备份服务器数据.数据库数据等 不适合人工经常做的一些操作这里简单说下 shell Shell俗称壳,类似于DOS下的command ...

  8. linux批量修改文件名的shell脚本

    linux中批量修改文件名的shell脚本代码,主要是使用了rename,结合shell,喜欢的朋友可以参考下 使用 rename 命令  ========================  NAME ...

  9. Linux 小知识翻译 - 「Shell 脚本」

    这次说说「Shell 脚本」. 根据上回的介绍,Shell就是「作为联系Linux和用户的接口而存在的软件」.在Linux环境中,通过Shell来操作系统很普遍. 这里,考虑到有时候可能想要「多次的进 ...

随机推荐

  1. web api 文档声明

    namespaceHelloWebAPI.Controllers{     usingHelloWebAPI.Models;     usingSystem;     usingSystem.Coll ...

  2. OpenGLES 怎样在十天内掌握线性代数 - 希望这是真的!

    OpenGLES 怎样在十天内掌握线性代数 - 希望这是真的! 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致&q ...

  3. 【拆点费用流】【HDU1853】【 Cyclic Tour】

    题意: 有N个城市,M条单向路,Tom想环游全部城市,每次至少环游2个城市,每个城市只能被环游一次.由于每条单向路都有长度,要求游遍全部城市的最小长度. // 给定一个有向图,必须用若干个环来覆盖整个 ...

  4. js类的几种写法

    我们常用的有以下几种方法来用JavaScript写一个“类”: 1. 构造函数(public属性和方法) 1: function Person(iName, iAge){ 2: this.name=i ...

  5. 【27前端】CSS Reset

    CSS reset就像是一种宁可错杀三千不可放过一个的做法. 一个最简单粗暴的css reset解决方案 *{ margin:0; padding:0; } 多余的话我就不再累赘,想要更多可以参考我的 ...

  6. Intent组件

    Android页面之间的跳转可以分为几类,比如有A和B两个页面,从A页面直接跳转到B页面,这样的跳转比较简单,或者从A页面跳转到B页面但是需要传送数据.在Android中,页面的跳转离不开Intent ...

  7. web.config详解

    在开发中经常会遇到这样的情况,在部署程序时为了保密起见并不将源代码随项目一同发布,而我们开发时的环境与部署环境可能不一致(比如数据库不一样),如果在代码中保存这些配置这些信息部署时需要到用户那里更改代 ...

  8. 5.7 cm server-agent 会出现无法启动

    异常信息如下: 离线安装cloudera-scm-agent5.7的Unable to create the pidfile问题 在离线安装Cloudera Manager启动agent出现了如下异常 ...

  9. HDU 1017 - A Mathematical Curiosity

    题目简单,格式酸爽.. #include <iostream> using namespace std; int ans,n,m,p; int main() { cin>>p; ...

  10. html5介绍

    html5与html4的区别   (h5 and h4)   什么是OPOA   1,    浏览器对h5的支持情况 2,    历史 --- h5         2004年,whatwg 提出 w ...