Linux Shell实例精讲学习笔记

第一章:shell基础

●umask   --查看当前用户创建文件或文件夹时的默认权限

eg:

[test@szbirdora 1]$umask

0002

[test@szbirdora 1]$ls -lh

-rw-rw-r--     test test  myfile   

drwxrwxr-x   test test 1

上面的例子中我们看到由test默认创建的文件myfile和文件夹1的权限分别为664,775.而通过umask查到的默认权限为0002.所以可以推断出umask的计算算法为:

umask                    file                      directory

0                          6                          7

1                          5                          6

2                          4                          5

3                          3                          4

4                          2                          3

5                          1                          2

6                          0                          1

7                          0                          0

●连接ln

硬连接 ln sourcefile targetfile                  连接后的target文件大小和source文件一样

软连接 ln -s sourcefile targetfile              类似于windows的快捷方式

●shell script 基本结构

#!/bin/bash                 --------bash shell开头必须部分

# description               --------注释部分(可有可无,为了阅读方便最好加以说明)

variable name=value         ---------变量部分,声明变量,赋值

control segment             ---------流程控制结构,如判断、循环、顺序

eg.

helloworld.sh

#!/bin/bash

# This is a helloworld shell script

printchar = "hello world"

echo $printchar

[test@szbirdora 1]$sh helloworld.sh

hello world

●shell 特性

①别名          alias                  eg. alias ll = “ls -l”

②管道          a |b                   将a命令的输出作为b命令的输入

eg.

ls |sort   将ls列举的项排序

③命令替换   a `b`                 将b命令的输出作为a命令的输入

eg.  

ls `cat myfile` 列举出cat myfile的输出项

④后台运行   nohup command&    可通过jobs -l查看后台运行的脚本

⑤重定向       >,<                      可以改变程序运行的输出来源和输入来源

⑥变量 可以用$varname 来调用变量

⑦特殊字符

                    `用来替换命令

                    \用来使shell无法认出其后的特殊字符,使其失去特殊含义

                    ;允许一行放多个命令

                    () 创建成组的命令 ??

                    {} 创建命令块 ??

第二章:变量和运算符

●本地变量:在用户现在的shell生命期的脚本中使用。设置变量:various_name=value.可用set 来查看。用readonly可以使变量只读。

●环境变量:用于当前用户下所有用户进程(不限于现在的shell)。

设置变量:export various_name=value。用env查看。

用readonly可以使变量只读。

●变量替换

echo ${variable name}                   显示实际值到variable name

echo ${variable name:+value}     如果设置了variable name,则显示其值,否则为空

echo ${variable name:?value}     如果未设置variable name,则显现用户定义错误信息value

echo ${variable name:-value}      如果未设置,则显示其值

echo ${variable name:=value}      如果未设置,则设置其值,并显示

●清除变量                                    unset variable name

●位置变量

位置变量表示$0,$1,$2...$9

$0 ----脚本名字

$1 ----根据参数位置表示参数1

eg.

#! /bin/bash

#parm.sh

echo "This is script name : $0"

echo "This is parameter 1: $1"

echo "This is parameter 2: $2"

[test@szbirdora 1]$sh parm.sh a b

This is script name : parm.sh

This is parameter 1: a

This is parameter 2: b

●向系统中传递位置变量

#!/bin/bash

#parm.sh

find /u01/test/1 -name $1 -print

[test@szbirdora 1]$ sh parm.sh myfile

/u01/test/1/myfile

●标准变量                              bash默认建立了一些标准环境变量,可在/etc/profile中定义

EXINIT

HOME

IFS

LOGNAME                                       --当前登录用户名

MAIL

MAILPATH

PATH

TERM                                              --终端信息

TZ                                                  --时区

PS1                                                --登录提示,如[test@szbirdora 1]$

[test@szbirdora 1]$ echo $PS1

[\u@\h \W]\$                                    --\u -user --\h -host --\W -document

PS2                                                --一命令多行,换行提示,如>

PWD                                                --当前目录

MAILCHECK                                   --每隔多少秒检查是否有新邮件

[test@szbirdora 1]$ echo $MAILCHECK

60

SHELL

MANPATH                                       --帮助文档位置

TERMINFO                                     --终端信息

●特殊变量

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

$*          以一个单字符串显示所有向脚本传递的参数,与位置变量不同,参数可超过9个

$$          脚本运行的当前进程ID号

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

$@         传递到脚本的参数列表,并在引号中返回每个参数

$-          显示shell使用的当前选项,与set命令功能相同

$?         显示最后命令的退出状态,0表示没有错误,其他表示有错误

eg.

#!/bin/bash

#parm

echo "this is shellname: $0"

echo "this is parm1 :    $1"

echo "this is parm2 :    $2"

echo "show parm number : $#"

echo "show parm list :   $*"

echo "show process id:   $$"

echo "show precomm stat: $?"

[test@szbirdora 1]$ sh parm.sh a b

this is shellname: parm.sh

this is parm1 :    a

this is parm2 :    b

show parm number : 2

show parm list :   a b

show process id:   24544

show precomm stat: 0

●影响变量的命令

declare 设置或显示变量

      -f     只显示函数名

       -r    创建只读变量

      -x     创建转出变量

       -i    创建整数变量

使用+替代-,可以颠倒选项的含义

export

      -p   显示全部全局变量

shift[n]    移动位置变量,调整位置变量,使$3赋予$2,使$2赋予$1     n 前移n

typeset     和declare同义

注意:双引号不能解析$,\,`三个字符,所以在双引号中可以引用变量、转义字符、替换变量

单引号可以解析,所以单引号中引用变量等无效

[test@szbirdora 1]$ echo "$test"

test

[test@szbirdora 1]$ echo '$test'

$test

●运算符类型

⒈按位运算符

~    取反

<<   左移运算符

>>   右移运算符

&    与

|     或

^     异或

$[ ]    表示形式告诉shell对方括号中表达式求值 $[a+b]

2.逻辑运算符

&&

||

>,<,=,!=

3.赋值运算符

let variablename1 +=variablename1+ varablename2

第三章 shell的输入和输出

1.echo    echo [option] string

            -e 解析转移字符

           -n 回车不换行,linux系统默认回车换行

转移字符 \c \t \f \n

#!/bin/bash

#echo

echo -e "this echo's 3 newlne\n\n\n"

echo "OK"

echo

echo "this is echo's 3 ewline\n\n\n"

echo "this log file have all been done">mylogfile.txt

[test@szbirdora ~]$ sh echod.sh

this echo's 3 newlne

OK

this is echo's 3 ewline\n\n\n

上面可以看到有-e则可以解析转移字符,没有不能解析。echo空输出为空

2.read 可以从键盘或文件的某一行文本中读入信息,并将其赋给一个变量

read variable1 variable2

eg.

#!/bin/bash

#readname

echo -n "first name:"

read firstname

echo -n "last name:"

read lastname

echo "this name is $firstname $lastname"

3.cat        显示文件的内容,创建内容,还可以显示控制字符

cat [options]filename1 filename2

                   -v   显示控制字符(Windows文件)

             cat命令不会分页显示,要分页可以采用more、less

4.管道|

5.tee     把输出的一个副本输送到标准输出,另一个副本拷贝到相应的文件中,一般与管道合用

              tee [options] files

              -a 在文件中追加

eg.

[test@szbirdora 1]$ echo |tee myfile

[test@szbirdora 1]$ cat myfile

将myfile文件置空

6.文件重定向

command>filename                                        ---覆盖输出

command>>filename                                      ---追加输出

command>filename>&1                                 ---把标准输出和标准错误重定向

command<

command

command<-                                                     --- 关闭标准输入

>nullfile.txt                                                       ---创建字节为0的文件

command1command3               ---按从左到右顺序执行

eg.

说明:myfile为空间

[test@szbirdora 1]$ df -lh>myfile

[test@szbirdora 1]$ cat myfile

Filesystem            Size Used Avail Use% Mounted on

/dev/sda1              20G 3.3G   16G 18% /

none                  2.0G     0 2.0G   0% /dev/shm

/dev/sda2              79G   17G   59G 23% /u01

/dev/sda4              28G 3.9G   22G 15% /u02

[test@szbirdora 1]$ df -lh>myfile

[test@szbirdora 1]$ cat myfile

Filesystem            Size Used Avail Use% Mounted on

/dev/sda1              20G 3.3G   16G 18% /

none                  2.0G     0 2.0G   0% /dev/shm

/dev/sda2              79G   17G   59G 23% /u01

/dev/sda4              28G 3.9G   22G 15% /u02

[test@szbirdora 1]$ df -lh>>myfile

[test@szbirdora 1]$ cat myfile

Filesystem            Size Used Avail Use% Mounted on

/dev/sda1              20G 3.3G   16G 18% /

none                  2.0G     0 2.0G   0% /dev/shm

/dev/sda2              79G   17G   59G 23% /u01

/dev/sda4              28G 3.9G   22G 15% /u02

Filesystem            Size Used Avail Use% Mounted on

/dev/sda1              20G 3.3G   16G 18% /

none                  2.0G     0 2.0G   0% /dev/shm

/dev/sda2              79G   17G   59G 23% /u01

/dev/sda4              28G 3.9G   22G 15% /u02

[test@szbirdora 1]$ cat >>myfile<

> China

> Hubei

> Suizhou

> exit

[test@szbirdora 1]$ cat myfile

China

Hubei

Suizhou

7.exec        可以用来替代当前shell。现有任何环境变量都会清除

第四章 控制流结构

1.if语句

if 条件1

then

命令1

elif 条件2

then

命令2

else

命令3

fi

------------------

if 条件

then 命令

fi

eg:

#!/bin/bash

#if test

#this is a comment line

if [ "10" -lt "12" ];then

#yes 10 is less than 12

echo "yes,10 is less than 12"

else

echo "no"

fi

注意:if语句必须以fi终止

   "10" 前一个空格,“12”后也有一个空格。这个条件都是通过test命令来指定。条件表达为test expression或者[expression]

条件表达式中的比较函数

man test

NAME

       test - check file types and compare values

SYNOPSIS

       test EXPRESSION

       [ EXPRESSION ]

       [ OPTION

DESCRIPTION

       Exit with the status determined by EXPRESSION.

       --help display this help and exit

       --version

              output version information and exit

       EXPRESSION is true or false and sets exit status. It is one of:

       ( EXPRESSION )

              EXPRESSION is true

       ! EXPRESSION

              EXPRESSION is false

       EXPRESSION1 -a EXPRESSION2

              both EXPRESSION1 and EXPRESSION2 are true

       EXPRESSION1 -o EXPRESSION2

              either EXPRESSION1 or EXPRESSION2 is true

       [-n] STRING

              the length of STRING is nonzero

       -z STRING

              the length of STRING is zero

       STRING1 = STRING2

              the strings are equal

       STRING1 != STRING2

               the strings are not equal

       INTEGER1 -eq INTEGER2

              INTEGER1 is equal to INTEGER2

       INTEGER1 -ge INTEGER2

              INTEGER1 is greater than or equal to INTEGER2

       INTEGER1 -gt INTEGER2

              INTEGER1 is greater than INTEGER2

       INTEGER1 -le INTEGER2

              INTEGER1 is less than or equal to INTEGER2

       INTEGER1 -lt INTEGER2

              INTEGER1 is less than INTEGER2

       INTEGER1 -ne INTEGER2

              INTEGER1 is not equal to INTEGER2

       FILE1 -ef FILE2

              FILE1 and FILE2 have the same device and inode numbers

       FILE1 -nt FILE2

              FILE1 is newer (modification date) than FILE2

       FILE1 -ot FILE2

              FILE1 is older than FILE2

       -b FILE

              FILE exists and is block special

       -c FILE

              FILE exists and is character special

       -d FILE

              FILE exists and is a directory

       -e FILE

              FILE exists

       -f FILE

              FILE exists and is a regular file

       -g FILE

              FILE exists and is set-group-ID

       -h FILE

              FILE exists and is a symbolic link (same as -L)

       -G FILE

              FILE exists and is owned by the effective group ID

       -k FILE

              FILE exists and has its sticky bit set

       -L FILE

              FILE exists and is a symbolic link (same as -h)

       -O FILE

              FILE exists and is owned by the effective user ID

       -p FILE

              FILE exists and is a named pipe

       -r FILE

              FILE exists and is readable

       -s FILE

              FILE exists and has a size greater than zero

       -S FILE

              FILE exists and is a socket

       -t [FD]

              file descriptor FD (stdout by default) is opened on a terminal

       -u FILE

              FILE exists and its set-user-ID bit is set

       -w FILE

              FILE exists and is writable

       -x FILE

             FILE exists and is executable

eg.

#!/bin/bash

#if test

#this is a comment line

echo "Enter your filename:"

read myfile

if [ -e $myfile ]

then

   if [ -s $myfile ];then

    echo "$myfile exist and size greater than zero"

   else

    echo "$myfile exist but size is zero"

   fi

else

echo "file no exist"

fi

[test@szbirdora 1]$ sh iftest.sh

Enter your filename:

11

11 exist but size is zero

2.case语句

case语句为多选择语句。

case 值 in

模式1)

命令1

    ;;

模式2)

命令2

    ;;

esac

eg.

#!/bin/bash

#case select

echo -n "enter a number from 1 to 3:"

read ans

case $ans in

1)

echo "you select 1"

;;

2)

echo "you select 2"

;;

3)

echo "you select 3"

;;

*)

echo "`basename $0`:this is not between 1 and 3">&2

exit;

;;

esac

3.for 循环

for循环一般格式:

for 变量名 in 列表 (列表以空格作为分割)

do

命令1

命令2

done

eg:

#!/bin/bash

#forlist1

for loop in 1 2 3 4 5

do

echo $loop

done

4.until循环

until 条件

do

命令1

命令2

   ...

done

条件测试发生在循环末尾,所以循环至少可以执行一次。

5.

while循环

while 命令 (可以是一个命令也可以是多个,做条件测试)

do

命令1

命令2

      ...

done

注意:如果从文件中读入变量

6.break和continue控制

break跳出,continue跳过

第五章 文本过滤

1.正则表达式

一种用来描述文本模式的特殊语法,由普通字符以及特殊字符(元字符)组成

^    ----只匹配行首

$    ----只匹配行尾

*    ----匹配0个或多个此单字符

[]   ----只匹配[]内字符,可以使用-表示序列范围[1-5]

\    ----屏蔽一个元字符的特殊含义

.    ----匹配任意单字符

pattern\{n\} 只用来匹配前面pattern出现的次数,n为次数

pattern\{n,\}只用来匹配前面pattern出现的次数,至少为n

pattern\{n,m\}只用来匹配前面pattern出现的次数,次数在n-m之间

eg:

A\{3\}B   AAAB

A\{3,\}B AAAB AAAAB ...

A\{3,5\}B AAAB AAAAB AAAAAB

2.find命令     ----查找文件和目录

find pathname -options [-print -exec -ok]

pathname --查找的目录路径. .--表示当前目录,/表示根目录

-print 输出

-exec 对匹配的文件执行该参数所给出的shell命令,相应命令形式为'command'{} \;'    注意{}和\;之间的空格

-ok    与-exec相同,不过执行命令前会有提示

options   :

-name

-perm

-user

-group

-mtime -n +n (atime,-ctime) 修改时间(访问时间,创建时间)

-size n[c]

-type 查找某一类型的文件

eg.

[test@szbirdora 1]$ find ./ -mtime +5

./helloworld.sh

./nohup.out

查看./目录(当前)下修改时间超过5天的文件

3.grep介绍

grep -c 输出匹配行计数

grep -i 不区分大小写

grep -h 查询多文件时不显示文件名

grep -H 显示文件名

grep -l 查询多文件时只输出包含匹配字符的文件名

grep -n 显示匹配行及行号

grep -s 不显示不存在或不匹配文本的错误信息

grep -v 显示不包含匹配文本的所有行(过滤文本)

eg.

[test@szbirdora 1]$ grep -n 's.a' myfile

2:/dev/sda1              20G 3.3G   16G 18% /

4:/dev/sda2              79G   18G   58G 23% /u01

5:/dev/sda4              28G 3.9G   22G 15% /u02

[test@szbirdora 1]$ grep -n '2$' myfile

5:/dev/sda4              28G 3.9G   22G 15% /u02

grep -options '正则表达式' filename

4.sed介绍

sed不与初始化文件打交道,它操作的只是一个拷贝,然后所有的改动如果没有重定向到一个文件将输出到屏幕

sed是一种重要的文本过滤工具,使用一行命令或使用管道与grep与awk相结合。

sed调用:

1.命令 sed [options] '正则表达式sedcommand' input-files

2.script :sed [options] -f sedscript input-files

sed在文本中查询文本的方式

-行号,可以是简单数字,或一个行号范围

   -使用正则表达式

x ----行号

x,y ----行号范围从x到y

x,y! ---不包含行号x到y

sed命令选项:

-n 不打印

-c 下一个命令是编辑命令

-f 如果正在调用sed脚本文件

基本sed命令

p 打印匹配行

= 显示文本行号

a\ 在定位行号后附加新文本信息

i\在定位行号前插入新文本信息

d 删除定位行

c\用新文本替换定位文本

s 使用替换模式替换相应模式

r 从另一个文件中读文本

w 写文本到一个文件

q 第一个模式匹配完成后退去

l 显示与八进制ascii代码等价的控制字符

{}在定位行执行命令组

n 从一个文件中读文本下一行,并附加在下一行

g 将模式2粘贴到/pattern n/

y 传送字符

eg.

[test@szbirdora 1]$ sed -n '2p' myfile

c

打印myfile第2行

[test@szbirdora 1]$ sed -n '2,4p' myfile

c

f

b

打印第二行到第四行

[test@szbirdora 1]$ sed -n '/a/p' myfile

a

打印匹配a的行

[test@szbirdora 1]$ sed -n '2,/2/p' myfile

c

f

b

1

2

打印第二行到匹配'2'的行

s命令替换

[test@szbirdora 1]$ sed 's/b/a/p' myfile

a

a

a

c

d

e

替换b为a

多点编辑 -e

eg. (myfile包含a-e)

[test@szbirdora 1]$ sed -e '2d' -e 's/c/d/' myfile 11

a

d

d

e

sed命令r ---从文件中读取选定的行,读入输入文件中,显示在匹配的行后面

eg.

[test@szbirdora 1]$ cat 11

*******************Alaska***************

[test@szbirdora 1]$ sed '/a/r 11' myfile

a

*******************Alaska***************

b

c

d

e

写入命令:w   将输入文件中的匹配行写入到指定文件中

eg.

[test@szbirdora 1]$ cat 11

b

[test@szbirdora 1]$ sed -n '/a/w 11' myfile

[test@szbirdora 1]$ cat 11

a

追加:a   将文本追加到匹配行的后面。sed要求在a后加\,不止一行的以\连接

eg.

[test@szbirdora 1]$ sed '/b/a\****************hello*************\-------------china---------' myfile

a

b

****************hello*************-------------china---------

c

d

e

插入命令:i   将文本插入到匹配行的前面。sed要求在a后加\,不止一行的以\连接

eg.

[test@szbirdora 1]$ sed '/b/i\

> THE CHARACTER B IS BEST\

> *******************************' myfile

a

THE CHARACTER B IS BEST

*******************************

b

c

d

e

下一个:n 从一个文件中读文本下一行,并附加在下一行

退出命令 q 打印多少行后退出

eg.

[test@szbirdora 1]$ sed '3q' myfile

a alert

b best

c cook

sed script:

sed -f scriptfile myfile

5.awk介绍

awk可从文件或字符串值基于指定规则浏览和抽取信息

awk三种调用方式:

1.命令行方式

awk [-F field-sperator]'pattern{active}' input-files

awk [-F field-sperator]'command' input-files

awk脚本

所有awk命令插入一个文件,并使awk程序可执行,然后用awk命令解析器作为脚本的首行,以便通过键入脚本名称来调用。

awk命令插入一个单独文件

awk -f awk-script-file input-files

awk脚本由模式和动作组成

分隔符、域、记录

注意这里的$1,$2是域与位置变量$1,$2不一样。$0文件中的所有记录

eg:

awk '{print $0}' myfile

awk 'BEGIN {print "IP DATE ----"}{print $1"\t"$4}END{print "end-of -report"}

[test@szbirdora 1]$ df |awk '$1!~"dev"'|grep -v Filesystem

none                   1992400         0   1992400   0% /dev/shm

[test@szbirdora 1]$ df |awk '{if ($1=="/dev/sda1") print $0}'

/dev/sda1             20641788   3367972 16225176 18% /

[test@szbirdora shelltest]$ cat employee

Tom Jones       4424    5/12/66 543354

Mary Adams      5346    11/4/63 28765

Sally Chang     1654    7/22/54 650000

Billy Black     1683    9/23/44 336500

[test@szbirdora shelltest]$ awk '/[Aa]dams/' employee

Mary Adams      5346    11/4/63 28765

[test@szbirdora shelltest]$ sed -n '/[Aa]dams/p' employee

Mary Adams      5346    11/4/63 28765

[test@szbirdora shelltest]$ grep '[Aa]dams' employee

Mary Adams      5346    11/4/63 28765

三种命令方式下,使用模式匹配查询

[test@szbirdora shelltest]$ awk '{print $1}' employee

Tom

Mary

Sally

Billy

打印文件第一列

[test@szbirdora shelltest]$ awk '/Sally/{print $1"\t"$2}' employee

Sally   Chang

打印匹配Sally的行的第一列和第二列

[test@szbirdora shelltest]$ df |awk '$4>20884623'

Filesystem           1K-blocks      Used Available Use% Mounted on

/dev/sda2             82567220 17488436 60884616 23% /u01

/dev/sda4             28494620   4589172 22457992 17% /u02

打印df输出第四列大于××的行

格式输出:

打印函数—

[test@szbirdora shelltest]$ date

Mon Mar 10 15:15:47 CST 2008

[test@szbirdora shelltest]$ date |awk '{print "Month:" $2"\nYear:" $6}'

Month:Mar

Year:2008

[test@szbirdora shelltest]$ awk '/Sally/{print "\t\tHave a nice day,"$1"\t"$2}' employee

                Have a nice day,Sally   Chang

printf函数

[test@szbirdora shelltest]$ echo "LINUX"|awk '{printf "|%-10s|\n",$1}'

|LINUX     |

[test@szbirdora shelltest]$ echo "LINUX"|awk '{printf "|%10s|\n",$1}'

|     LINUX|

~匹配符

[test@szbirdora shelltest]$ awk '$1~/Tom/{print $1,$2}' employee

Tom Jones

awk 给表达式赋值

关系运算符:

<             小于

>             大于

==           等于

!=            不等于

>=           大于等于

<=           小于等于

~              匹配

!~            不匹配

eg.

[test@szbirdora shelltest]$ cat employee

Tom Jones       4424    5/12/66 543354

Mary Adams      5346    11/4/63 28765

Sally Chang     1654    7/22/54 650000

Billy Black     1683    9/23/44 336500

[test@szbirdora shelltest]$ awk '$2~/Adams/' employee

Mary Adams      5346    11/4/63 28765

条件表达式:

condition   expression1?expression2:expression3

eg.

awk '{max=($1>$2) ? $1:$2;print max}' filename

运算符

+,-,*,/,%,^,&&,||,!

[test@szbirdora shelltest]$ cat /etc/passwd |awk -F: '\

NF!=7{\

printf("line %d does not have 7 fields:%s\n",NR,$0)}\

$1!~/[A-Za-z0-9]/{printf("line %d,nonalphanumberic user id:%s\n",NR,$0)}\

$2=="*"{printf("line %d,no password:%s\n",NR,$0)}'

awk编程

递增操作符 x++,++x

递减操作符 x--,--x

BEGIN模块

BEGIN模块后面紧跟着动作块,在读入文件前执行。通常被用来改变内建变量的值,如:FS\RS\OFS,初始化变量的值和打印输出标题。

[test@szbirdora shelltest]$ awk 'BEGIN{print "HELLO WORLD"}'

HELLO WORLD

[test@szbirdora shelltest]$ awk 'BEGIN{print "---------LIST---------"}{print}END{print "------END--------"}' donors

---------LIST---------

Mike Harrington:(510) 548-1278:250:100:175

Christian Dobbins:(408) 538-2358:155:90:201

Susan Dalsass:(206) 654-6279:250:60:50

Archie McNichol:(206) 548-1348:250:100:175

Jody Savage:(206) 548-1278:15:188:150

Guy Quigley:(916) 343-6410:250:100:175

Dan Savage:(406) 298-7744:450:300:275

Nancy McNeil:(206) 548-1278:250:80:75

John Goldenrod:(916) 348-4278:250:100:175

Chet Main:(510) 548-5258:50:95:135

Tom Savage:(408) 926-3456:250:168:200

Elizabeth Stachelin:(916) 440-1763:175:75:300

------END--------

重定向和管道

输出重定向

awk输出重定向到一个文件需要使用输出重定向符,输出文件名需要用双引号括起来。

[test@szbirdora shelltest]$ awk -F: '{print $1,$2>"note"}' donors

[test@szbirdora shelltest]$ cat note

Mike Harrington (510) 548-1278

Christian Dobbins (408) 538-2358

Susan Dalsass (206) 654-6279

Archie McNichol (206) 548-1348

Jody Savage (206) 548-1278

Guy Quigley (916) 343-6410

Dan Savage (406) 298-7744

Nancy McNeil (206) 548-1278

John Goldenrod (916) 348-4278

Chet Main (510) 548-5258

Tom Savage (408) 926-3456

Elizabeth Stachelin (916) 440-1763

输入重定向

getline函数

[test@szbirdora shelltest]$ awk 'BEGIN{"date +%Y"|getline d;print d}'

2008

[test@szbirdora shelltest]$ awk -F"[ :]" 'BEGIN{printf "What is your name?";\

getline name<"/dev/tty"}\

$1~ name{print "Found\t" name "\ton line",NR"."}\

END{print "see ya," name "."}' donors

What is your name?Jody

Found   Jody    on line 5.

see ya,Jody.

[test@szbirdora shelltest]$ awk 'BEGIN{while(getline<"/etc/passwd">0)lc++;print lc}'

36

从文件中输入,如果得到一个记录,getline函数就返回1,如果文件已经到了末尾,则返回0,如果文件名错误则返回-1.

管道:

awk命令打开一个管道后要打开下一个管道需要关闭前一个管道,管道符右边可以使用“”关闭管道。在同一时间只有一个管道存在

[test@szbirdora shelltest]$ awk '{print $1,$2|"sort -r +1 -2 +0 -1"}' names

tony tram

john smith

dan savage

john oldenrod

barbara nguyen

elizabeth lone

susan goldberg

george goldberg

eliza goldberg

alice cheba

|后用""关闭管道

system函数

system("LINUX command")

system("cat" $1)

system("clear")

条件语句

1.if(){}

2.if(){}

else{}

3.if(){}

else if(){}

else if(){}

else{}

[test@szbirdora shelltest]$ awk -F: '{if ($3>250){printf "%-2s%13s\n",$1,"-----------good partman"}else{print $1}}' donors

循环语句

[test@szbirdora shelltest]$ awk -F: '{i=1;while(i<=NF){print NF,$i;i++}}' donors

循环控制语句break、continue

程序控制语句

next从输入文件中读取下一行,然后从头开始执行awk脚本

{if($1~/Peter/){next}

else{print}}

exit 结束awk语句,但不会结束END模块的处理。

数组:

awk '{name[x++]=$1;for(i=0;i

(P177)---2008.3.11

awk内建函数

sub(正则表达式,替换字符[,$n]) ---域n匹配正则表达式的字符串将被替换。

[test@szbirdora shelltest]$ awk '{sub(/Tom/,"Jack",$1);print}' employee

Jack Jones 4424 5/12/66 543354

Mary Adams      5346    11/4/63 28765

Sally Chang     1654    7/22/54 650000

Billy Black     1683    9/23/44 336500

Jack He 3000 8/22/44 320000

index函数 index(字符串,子字符串) 子字符串在字符串中的位置

[test@szbirdora shelltest]$ awk 'BEGIN{a=index("hello","llo");print a}'

3

length函数 length(string) 字符串的长度

[test@szbirdora shelltest]$ awk 'BEGIN{a=length("hello world");print a}'

11

substr函数 substr(字符串,开始位置[,子字符串长度])

[test@szbirdora shelltest]$ awk 'BEGIN{a=substr("hello world",7);print a}'

world

[test@szbirdora shelltest]$ awk 'BEGIN{a=substr("hello world",7,3);print a}'

wor

match(string,正则表达式) 找出字符串中第一个匹配正则表达式的位置,其内建变量RSTART为匹配开始位置,RLENGTH为匹配开始后字符数

[test@szbirdora shelltest]$ awk '{a=match($0,/Jon/);if (a!=0){print NR,a}}' employee

1 5

[test@szbirdora shelltest]$ awk '{a=match($0,/Jon/);if (a!=0){print NR,a,RSTART,RLENGTH}}' employee

1 5 5 3

toupper和tolower函数

[test@szbirdora shelltest]$ awk 'BEGIN{a=toupper("hello");print a}'

HELLO

split函数 split(string,array,fieldseperator)

[test@szbirdora shelltest]$ awk 'BEGIN{"date"|getline d;split(d,date);print date[2]}'

Mar

时间函数

systime() ----1970年1月1日到当前忽略闰年得出的秒数。

strftime(格式描述,时间戳)

[test@szbirdora shelltest]$ awk 'BEGIN{d=strftime("%T",systime());print d}'

13:08:09

[test@szbirdora shelltest]$ awk 'BEGIN{d=strftime("%D",systime());print d}'

03/12/08

[test@szbirdora shelltest]$ awk 'BEGIN{d=strftime("%Y",systime());print d}'

2008

6.sort介绍

sort:

     -c 测试文件是否已经排序

     -m 合并两个排序文件

     -u 删除所有复制行

     -o 存储sort结果的输出文件名

     -t 域分隔符;用非空格或tab键分割域

     +n n为域号,使用此域号开始排序 (注意0是第一列)

     -r 逆序排序

     n 指定排序是域上的数字排序项

[test@szbirdora 1]$ df -lh|grep -v 'Filesystem'|sort +1

none                  2.0G     0 2.0G   0% /dev/shm

/dev/sda1              20G 3.3G   16G 18% /

/dev/sda4              28G 3.9G   22G 15% /u02

/dev/sda2              79G   17G   59G 23% /u01

uniq [option]files 从一个文本文件中去除或禁止重复行

     -u 只显示不重复行

     -d 只显示有重复数据行,每重复行只显示其中一行

     -c 打印每一重复行出现次数

     -f n为数字,前n个域被忽略

注意要先排序

7.split cut join 分割和合并文件命令

[test@szbirdora 1]$ split -l 2 myfile split   (每两行分割为一个以split名称开头的文件)

[test@szbirdora 1]$ ls

case.sh df.out helloworld.sh iftest.sh myfile nohup.out nullfile.txt parm.sh splitaa splitab splitac splitad splitae

[test@szbirdora 1]$ cat splitaa

Filesystem            Size Used Avail Use% Mounted on

/dev/sda1              20G 3.3G   16G 18% /

第六章 shell函数

1.定义函数

funcation name()

{

   command1

   ....

}

函数名()

   {

   command1

   ...

   }

eg.

#!/bin/bash

#hellofun

function hello()

{

echo "hello,today is `date`"

return 1

}

2.函数调用

#!/bin/bash

#hellofun

function hello()

{

echo "hello,today is `date`"

return 1

}

echo "now going to the function hello"

hello

echo "back from the function"

所以调用函数只需要在脚本中使用函数名就可以了。

3.参数传递

像函数传递参数就像在脚本中使用位置变量$1,$2...$9

4.函数文件

函数可以文件保存。在调用时使用". 函数文件名"(.+空格+函数文件名)

如:

hellofun.sh

#!/bin/bash

#hellofun

function hello()

{

echo "hello,today is `date`"

return 1

}

func.sh

#!/bin/bash

#func

. hellofun.sh

echo "now going to the function hello"

echo "Enter yourname:"

read name

hello $name

echo "back from the function"

[test@szbirdora 1]$ sh func.sh

now going to the function hello

Enter yourname:

hh

hello,hh today is Thu Mar 6 15:59:38 CST 2008

back from the function

5.检查载入函数 set

删除载入函数 unset 函数名

6.函数返回状态值 return 0、return 1

7.脚本参数的传递

shift命令

shift n 每次将参数位置向左偏移n

#!/bin/bash

#opt2

usage()

{

echo "usage:`basename $0` filename"

}

totalline=0

if [ $# -lt 2 ];then

    usage

fi

while [$# -ne 0]

do

    line=`cat $1|wc -l`

    echo "$1 : ${line}"

    totalline=$[$totalline+$line]

    shift                               #   $# -1

done

echo "-----"

echo "total:${totalline}"

[test@szbirdora 1]$ sh opt2.sh myfile df.out

myfile : 10

df.out : 4

-----

total:14

8.getopts命令

获得多个命令行参数

getopts ahfvc OPTION   --从ahfvc一个一个读出赋值给OPTION.如果参数带有:则把变量赋值给:前的参数--:只能放在末尾。

该命令可以做获得命令的参数

#!/bin/bash

#optgets

ALL=false

HELP=false

FILE=false

while getopts ahf OPTION

do

   case $OPTION in

    a)

      ALL=true

      echo "ALL is $ALL"

      ;;

    h)

      HELP=true

      echo "HELP is $HELP"

      ;;

    f)

      FILE=true

      echo "FILE is $FILE"

      ;;

    \?)

      echo "`basename $0` -[a h f] file"

      ;;

    esac

done

[test@szbirdora 1]$ sh optgets.sh -a -h -m

ALL is true

HELP is true

optgets.sh: illegal option -- m

optgets.sh -[a h f] file

getopts表达式:

while getopts p1p2p3... var    do

    case var in

    ..)

    ....

   esac

done

如果在参数后面还需要跟自己的参数,则需要在参数后加:

如果在参数前面加:表示不想将错误输出

getopts函数自带两个跟踪参数的变量:optind,optarg

optind初始值为1,在optgets处理完一次命令行参数后加1

optarg包含合法参数的值,即带:的参数后跟的参数值

有了前面的学习,下面只记载一些在学习的过程中又忘了了一些知识点。所以记录是零散的。

1.

shopt bash2.0以上新的命令,功能和set类似。

给变量赋值时等号两边不可留空格。

环境变量一般使用大写。

2.

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

$* 以一个单字符串显示所有向脚本传递的参数,与位置变量不同,参数可超过9个

$$ 脚本运行的当前进程ID号

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

$@ 传递到脚本的参数列表,并在引号中返回每个参数

$- 显示shell使用的当前选项,与set命令功能相同

$? 显示最后命令的退出状态,0表示没有错误,其他表示有错误

3.

echo 命令中使用" "无法直接识别转义字符,必须使用选项 -e,但可以使用$和`引用变量和命令替换。

$[] 告诉shell对方括号中表达式求值 $[a+b],如$[1+8]

4.

tee

把输出的一个副本输送到标准输出,另一个副本拷贝到相应的文件中

tee -a file       -----a表示在文件末尾追加,不要-a则覆盖

该命令一般与管道合用

5.

command>filename>&1 ---把标准输出和标准错误重定向

command<

eg:

sqlplus / as sysdba <

show parameters

exit

EOF

6.命令替换有两种方式,老的korn风格的`linux command`和新的bash风格$(linux command)

7.定义数组

declare -a arry=(a1 a2 a3 ...)

echo ${a[n]}

8.read使用

read -a arryname     ---读入为数组

read -p prompt      ----输出提示,并把提示后的输入存到REPLY内建变量中

[test@szbirdora 1]$ read -p "Enter your name:"

Enter your name:jack

[test@szbirdora 1]$ echo $REPLY

jack

[test@szbirdora 1]$ read -a name

jack tom susan

[test@szbirdora 1]$ echo ${name[2]}

susan

[test@szbirdora 1]$ echo ${name[0]}

jack

9.多进制整型变量表示

declare -i number

number=base#number_in_the_base

如:

declare -i number

number=2#101

number=16#A9

10.条件语句if then fi中if后的表达式可以是条件表达式(布尔表达式)或一组命令,如果是布尔表达式则表达式为真执行then后的语句,如果是命令组,则命令组状态($?)为0执行then后面的语句。但如果是C shell则if后只能跟布尔表达式。

11.here文档和case建立菜单:

eg.

echo "Select a terminal type:"

cat <

1) linux

2)xterm

3)sun

EOF

read choice

case $choice in

1)TERM=linux

   export TERM

   ;;

2)TERM=xterm

   export TERM

;;

3)TERM=sun

   export TERM

;;

*) echo "please select correct chioce,ths!"

;;

esac

echo "TERM is $TERM"

12.循环比较:

for variable in wordlist;do     ---从文件或列表中给定的值循环

while command;do       ----当command的返回值为0时做循环

until command;do        ----当command的返回值不为0时作循环

select循环菜单

用 select建立菜单,需要用PS3来提示用户输入,输入保存在REPLY内建变量中,REPLY的值与内建菜单关联。在构建菜单过程中可以使用 COLUMNS和LINES两个变量,COLUMNS决定菜单的列宽度,LINES决定可显示的行数。select和case命令联用可以有效的构造循环 菜单。

eg

#!/bin/bash

#Author: hijack

#Usage:Menu

t=0

j=0

d=0

PS3="Please choose one of the three boys or quit:"

select choice in Tom Jack David Quit

do

case $choice in

Tom)

t=$t+1

if (($t==5));then

echo "Tom win"

break

fi

;;

Jack)

j=$j+1

if (($j==5));then

echo "Jack win"

break

fi

;;

David)

d=$d+1

if (($d==5));then

echo "David win"

break

fi

;;

Quit) exit 0;;

*) echo "$REPLY is invalide choice" 1>&2

   echo "Try again!"

;;

esac

done

[test@szbirdora 1]$ sh menu

1) Tom

2) Jack

3) David

4) Quit

Please choose one of the three boys or quit:1

Please choose one of the three boys or quit:2

Please choose one of the three boys or quit:1

Please choose one of the three boys or quit:1

Please choose one of the three boys or quit:1

Please choose one of the three boys or quit:1

Tom win

12.set 设置位置变量,shift移动位置变量。

set tom jack david -----$1 tom $2 jack $3 david

echo $*

tom jack david

shift 2                     -----移动两个位置,$1,$2删除

echo $*

david

eg:

#!/bin/bash

#Name:shift

#Author : Hijack

#Usage:shift test

#Date:080320

while (($#>0))

do

    echo "$*"

    shift

done

[test@szbirdora 1]$ ./shift 1 2 3 4 5 6 7

1 2 3 4 5 6 7

2 3 4 5 6 7

3 4 5 6 7

4 5 6 7

5 6 7

6 7

7

13。 break n   ---n 代表退出第几层循环,默认退出一层。continue n 类似

#!/bin/bash

#Name   : Mulloop

#Author : Hijack

#Usage : break test

declare -i x=0

declare -i y=0

while true

do

while (( x<20 ))

do

   x=$x+1

   echo $x

   if (( $x==10 ));then

    echo "if"

    break

   fi

done

echo "loop end"

y=$y+1

if (($y>5));then

   break

fi

done

[test@szbirdora 1]$ sh mulloop

1

2

3

4

5

6

7

8

9

10

if

loop end

11

12

13

14

15

16

17

18

19

20

loop end

loop end

loop end

loop end

loop end

#!/bin/bash

#Name   : Mulloop

#Author : Hijack

#Usage : break test

declare -i x=0

declare -i y=0

while true

do

while (( x<20 ))

do

   x=$x+1

   echo $x

   if (( $x==10 ));then

    echo "if"

    break 2

   fi

done

echo "loop end"

y=$y+1

if (($y>5));then

   break

fi

done

[test@szbirdora 1]$ sh mulloop

1

2

3

4

5

6

7

8

9

10

if

14.循环的IO重定向

使用">","|"等重定向符实现循环的IO重定向

如 while ;do

      done >temp$$

    for in

    do

    done |sort

eg

给文件的每行加一个行号,写入文件中

#!/bin/bash

#Name    : loopred

#Author : Hijack

#Usage   : add linenum to the file

#Program : read line to loop from file,add linenum,output to tempfile,mv tempfile to file

declare -i count=0

declare -i total=0

total=`sed -n "$=" $1`

cat $1 | while read line

do

    (($count==0))&& echo -e "Processing file $1.....\n"> /dev/tty

    count=$count+1

    echo -e "$count\t$line"

    (($count==$total))&& echo "Process finish,total line number is $count" > /dev/tty

done >temp$$

mv temp$$ $1

[test@szbirdora 1]$ sh loopred testmv

Processing file testmv.....

Process finish,total line number is 19

[test@szbirdora 1]$ vi testmv

1       /u01/test

2       /u01/test/1

3       /u01/test/1/11

4       /u01/test/1/forlist.sh

5       /u01/test/1/optgets.sh

6       /u01/test/1/whiletest.sh

7       /u01/test/1/func.sh

8       /u01/test/1/helloworld.sh

9       /u01/test/1/df.out

10      /u01/test/1/nullfile.txt

11      /u01/test/1/iftest.sh

12      /u01/test/1/myfile

13      /u01/test/1/opt2.sh

14      /u01/test/1/0

15      /u01/test/1/case.sh

16      /u01/test/1/nohup.out

17      /u01/test/1/hellfun.sh

18      /u01/test/1/parm.sh

19      /u01/test/1/test

15。在done后面加&使循环在后台运行,程序继续执行。

16.在函数内可以使用local定义本地变量,local variable。

17.陷阱信号 trap --当一个信号发出传递给进程时,进程进行相关操作,信号包括中断等

     trap ‘command;command’ signal-num                          #trap设置时执行命令

     trap “command;command” signal-num                         #信号到达时执行命令

eg:

[root@linux2 ~]# trap "echo -e 'hello world\n';ls -lh" 2

[root@linux2 ~]# hello world                                             ---ctrl+c

total 100K

-rw-r--r-- 1 root root 1.4K Nov 14 16:53 anaconda-ks.cfg

drwxr-xr-x 2 root root 4.0K Nov 23 13:11 Desktop

-rw-r--r-- 1 root root 53K Nov 14 16:53 install.log

-rw-r--r-- 1 root root 4.9K Nov 14 16:53 install.log.syslog

drwxr-xr-x 2 root root 4.0K Nov 22 13:03 vmware

你可能感兴趣的:(读书笔记)