Shell 编程 - CAS

113
Shell 编程 曙光信息产业有限公司 技术支持中心

Transcript of Shell 编程 - CAS

Page 1: Shell 编程 - CAS

Shell 编程

曙光信息产业有限公司

技术支持中心

Page 2: Shell 编程 - CAS

Index

• The shell of Linux

• Bourne Shell Programming

• find.and.regular.expression

• text manipulation

2Shell 编程

Page 3: Shell 编程 - CAS

The shell of Linux

• Bourne shell (sh),

• C shell (csh),

• Korn shell (ksh),

• TC shell (tcsh),

• Bourne Again shell (bash)

3Shell 编程

Page 4: Shell 编程 - CAS

Difference between programming and scripting languages

– Programming languages are generally a lot more powerful and a lot faster than scripting languages. Programming languages generally start from source code and are compiled into an executable. This executable is not easily ported into different operating systems.

– A scripting language also starts from source code, but is not compiled into an executable. Rather, an interpreter reads the instructions in the source file and executes each instruction. Interpreted programs are generally slower than compiled programs. The main advantage is that you can easily port the source file to any operating system.

4Shell 编程

Page 5: Shell 编程 - CAS

The first bash program

• We must know how to use a text editor. There are two major text editors in Linux:

– vi, emacs (or xemacs).

• So fire up a text editor; for example:

– $ vi &

and type the following inside it:

– #!/bin/bash

echo “Hello World”

• The first line tells Linux to use the bash interpreter to run this script. We call it hello.sh. Then, make the script executable:

– $ chmod 700 hello.sh

– $ ls –l

-rwx------ hello.sh

5Shell 编程

Page 6: Shell 编程 - CAS

The first bash program

• To execute the program:

– $ hello.sh

-bash: hello.sh: command not found

The home directory (where the command hello.sh is located)

is not in the variable PATH

– echo $PATH

:bin:/usr/bin:…

We must specify the path of hello.sh

– $/home/srinaldi/Scripts/hello.sh

– $./hello.sh

6Shell 编程

Page 7: Shell 编程 - CAS

The second bash program

• We write a program that copies all files into a directory, and then deletes the

directory along with its contents. This can be done with the following

commands:

– $ mkdir trash

$ cp * trash

$ rm -rf trash

$ mkdir trash

• Instead of having to type all that interactively on the shell, write a shell

program instead:

– $ cat trash

#!/bin/bash

# this script deletes some files

cp * trash

rm -rf trash

mkdir trash

echo “Deleted all files!”7Shell 编程

Page 8: Shell 编程 - CAS

• Bourne Shell Programming

Shell 编程 75

Page 9: Shell 编程 - CAS

Bourne Shell Programming

• Certainly the most popular shell is “bash”. Bash

is the shell that will appear in the GNU operating

system. Bash is an sh-compatible shell that

incorporates useful features from the Korn shell

(ksh) and C shell (csh).

• bash is not only an excellent command line shell,

but a scripting language in itself. Shell scripting

allows us to use the shell's abilities and to

automate a lot of tasks that would otherwise

require a lot of commands.

76Shell 编程

Page 10: Shell 编程 - CAS

Borne Shell

Backgroundm Early Unix shell that was written by Steve

Bourne of AT&T Bell Lab.

m Basic shell provided with many commercial versions of UNIX

m Many system shell scripts are written to run under Bourne Shell

m A long and successful history

Shell 编程 77

Page 11: Shell 编程 - CAS

Bourne Shell Programming

• Control structures– if … then

– for … in

– while

– until

– case

– break and continue

Shell 编程 78

Page 12: Shell 编程 - CAS

if … then

• Structure

if test-command

then

commands

fi

Example:

if test “$word1” = “$word2”

then

echo “Match”

fi

79Shell 编程

Page 13: Shell 编程 - CAS

test

• Command test is a built-in command • Syntax

test expression[ expression ]

– The test command evaluate an expression – Returns a condition code indicating that the expression is

either true (0) or false (not 0)

• Argument– Expression contains one or more criteria

• Logical AND operator to separate two criteria: -a • Logical OR operator to separate two criteria: -o• Negate any criterion: !• Group criteria with parentheses

– Separate each element with a SPACE80Shell 编程

Page 14: Shell 编程 - CAS

Test Criteria

• Test Operator for integers: int1 relop int2

Relop Description

-gt Greater than

-ge Greater than or equal to

-eq Equal to

-ne Not euqal to

-le Less than or equal to

-lt Less than

81Shell 编程

Page 15: Shell 编程 - CAS

Exercise

• Create a shell script to check there is at least one parameter

– Something like this:

if test $# -eq 0

then

echo “ you must supply at least one arguments”

exit 1

fi

…82Shell 编程

Page 16: Shell 编程 - CAS

Test Criteria

• The test built-in options for filesOption Test Performed on file

-d filename Exists and is a directory file

-f filename Exists and is a regular file

-r filename Exists and it readable

-s filename Exists and has a length greater than 0

-u filename Exists and has setuid bit set

-w filename Exists and it writable

-x filename Exists and it is executable

… … … …

83Shell 编程

Page 17: Shell 编程 - CAS

Exercise

• Check weather or not the parameter is a non-zero readable file name– Continue with the previous script and add

something likeif [ -r “$filename” –a –s “$filename” ]

then

… …

fi

84Shell 编程

Page 18: Shell 编程 - CAS

Test Criteria

• String testingCriteria meaning

String True if string is not the null string

-n string True if string has a length greater than zero

-z string True if string has a length of zero

String1 = string2 True if string1 is equal to string2

String1 != string2 True if string1 is not equal to string2

85Shell 编程

Page 19: Shell 编程 - CAS

Exercise

• Check users confirmation

– Frist, read user input

echo -n “Please confirm: [Yes | No] “

read user_input

– Then, compare it with standard answer ‘yes’

if [ “$user_input” = Yes ]

then

echo “Thanks for your confirmation!”

Fi

86Shell 编程

Page 20: Shell 编程 - CAS

if…then…else

• Structureif test-command

thencommands

elsecommands

fi

– You can use semicolon (;) ends a command the same way a NEWLINE does.

if [ … ]; then… …

fi

if [ 5 = 5 ]; then echo "equal"; fi

87Shell 编程

Page 21: Shell 编程 - CAS

if…then…elif

• Structureif test-command

thencommands

elif test-commandthen

commands...

elsecommands

fi

88Shell 编程

Page 22: Shell 编程 - CAS

Debugging Shell Scripts

• Display each command before it runs the command– Set the –x option for the current shell

• $set –x

– Use the –x to invoke the script• $sh –x command arguments

– Add the set command at the top of the script• set –x

• Then each command that the script executes is preceded by a plus sign (+)– Distinguish the output of trace from any output that the

script produces

• Turn off the debug with set +x

89Shell 编程

Page 23: Shell 编程 - CAS

for… in

• Structurefor loop-index in argument_listdo

commandsdone

Example:for file in *do

if [ -d “$file” ]; thenecho $file

fidone

90Shell 编程

Page 24: Shell 编程 - CAS

for

• Structurefor loop-index

do

commands

done

– Automatically takes on the value of each of command line arguments, one at a time. Which implies

for arg in “$@”91Shell 编程

Page 25: Shell 编程 - CAS

while

• Structure

while test_command

do

commands

done

Example:

while [ “$number” –lt 10 ]

do

… …

number=`expr $number + 1`

done

92Shell 编程

Page 26: Shell 编程 - CAS

until

• Structureuntil test_commanddo

commandsdone

Example:secretname=jennyname=nonameuntil [ “$name” = “$secretname” ]do

echo “ Your guess: \c”read name

done

93Shell 编程

Page 27: Shell 编程 - CAS

break and continue

• Interrupt for, while or until loop• The break statement

– transfer control to the statement AFTER the done statement

– terminate execution of the loop• The continue statement

– Transfer control to the statement TO the done statement

– Skip the test statements for the current iteration– Continues execution of the loop

94Shell 编程

Page 28: Shell 编程 - CAS

Example:

for index in 1 2 3 4 5 6 7 8 9 10do

if [ $index –le 3 ]; thenecho continuecontinue

fiecho $indexif [ $index –ge 8 ]; then

echo “break”break

fidone

95Shell 编程

Page 29: Shell 编程 - CAS

case

• Structurecase test_string inpattern-1 )

commands_1;;

pattern-2 )commands_2

;;… …esac

• default case: catch all pattern* )

96Shell 编程

Page 30: Shell 编程 - CAS

case

• Special characters used in patternsPattern Matches

* Matches any string of characters.

? Matches any single character.

[…] Defines a character class. A hyphen specifies a range of characters

| Separates alternative choices that satisfy a particular branch of the case structure

97Shell 编程

Page 31: Shell 编程 - CAS

Example

#!/bin/shecho “\n Command MENU\n”echo “ a. Current data and time”echo “ b. Users currently logged in”echo “ c. Name of the working directory\n”echo “Enter a,b, or c: \c”read answerecho case “$answer” in

a)date;;

b)who;;

c) pwd;;

*) echo “There is no selection: $answer”;;

esac 98Shell 编程

Page 32: Shell 编程 - CAS

Built-in: exec

• Execute a command:

– Syntax: exec command argument

– Run a command without creating a new process

• Quick start

• Run a command in the environment of the original process

• Exec does not return control to the original program

• Exec can be the used only with the last command that you want to run in a script

• Example, run the following command in your current shell, what will happen?

$exec who

101Shell 编程

Page 33: Shell 编程 - CAS

Built-in: exec

• Redirect standard output, input or error of a shell script from within the script

• exec < infile• exec > outfile 2> errfile

– Example:sh-2.05b$ more redirect.shexec > /dev/ttyecho "this is a test of redirection"

sh-2.05b$ ./redirect.sh 1 > /dev/null 2 >& 1this is a test of redirection

102Shell 编程

Page 34: Shell 编程 - CAS

Catch a signal: builtin trap

• Built-in trap – Syntax: trap ‘commands’ signal-numbers– Shell executes the commands when it catches one of the

signals– Then resumes executing the script where it left off.

• Just capture the signal, not doing anything with ittrap ‘ ‘ signal_number

– Often used to clean up temp files– Signals

• SIGHUP 1 disconnect line• SIGINT 2 control-c• SIGKILL 9 kill with -9• SIGTERM 15 default kill• SIGSTP 24 control-z• …

103Shell 编程

Page 35: Shell 编程 - CAS

Example

[ruihong@dafinn ~/cs3451]$ more inter

#!/bin/sh

trap 'echo PROGRAM INTERRUPTED' 2

while true

do

echo "programming running."

sleep 1

done

104Shell 编程

Page 36: Shell 编程 - CAS

A partial list of built-in

• bg, fg, jobs job control

• break, continue change the loop

• cd, pwd working directory

• echo, read display/read

• eval scan and evaluate the command

• exec execute a program

• exit exit from current shell

• export, unset export/ remove a val or fun

• test compare arguments

105Shell 编程

Page 37: Shell 编程 - CAS

A partial list of builtin

• kill sends a signal to a process or job

• set sets flag or argument

• shift promotes each command line argument

• times displays total times for the current shell and

• trap traps a signal

• type show whether unix command, build-in, function

• umask file creation mask

• wait waits for a process to terminate.

• ulimit print the value of one or more resource limits 106Shell 编程

Page 38: Shell 编程 - CAS

functions

• A shell function is similar to a shell script– It stores a series of commands for execution at a later time.

– The shell stores functions in the memory

– Shell executes a shell function in the same shell that called it.

• Where to define– In .profile

– In your script

– Or in command line

• Remove a function– Use unset built-in

107Shell 编程

Page 39: Shell 编程 - CAS

functions

• Syntaxfunction_name(){

commands}

• Example:sh-2.05b$ whoson()> {> date> echo "users currently logged on"> who> }sh-2.05b$ whosonTue Feb 1 23:28:44 EST 2005users currently logged onruihong :0 Jan 31 08:46ruihong pts/1 Jan 31 08:54 (:0.0)ruihong pts/2 Jan 31 09:02 (:0.0)

108Shell 编程

Page 40: Shell 编程 - CAS

Example

sh-2.05b$ more .profilesetenv(){

if [ $# -eq 2 ]then

eval $1=$2export $1

elseecho "usage: setenv NAME VALUE" 1>&2

fi}sh-2.05b$. .profilesh-2.05b$ setenv T_LIBRARY /usr/local/tsh-2.05b$ echo $T_LIBRARY/usr/local/t

109Shell 编程

Page 41: Shell 编程 - CAS

Exercise

• Let’s look at some system scripts – /etc/init.d/syslog

– /etc/init.d/crond

110Shell 编程

Page 42: Shell 编程 - CAS

Summary

• Shell is a programming language

• Programs written in this language are called shell scripts.– Variable

– Built-in

– Control structure

– Function

– Call utilities outside of shell• find, grep, awk

111Shell 编程

Page 43: Shell 编程 - CAS

• Shell 中的find和正则表达式

112Shell 编程

Page 44: Shell 编程 - CAS

使用find和xargs

• find 命令选项

• 使用find 命令不同选项的例子

• 配合find 使用xargs的例子

• find命令的一般格式– find pathname -options [-print -exec -ok]

– -print find 命令将匹配的文件输出到标准输出

– -exec find 命令对匹配到的文件执行该参数给出的shell命令,命令格式为 ‘command’{} \

113Shell 编程

Page 45: Shell 编程 - CAS

find命令选项

• -name 按照文件名查找文件

• -perm 按照文件权限查找文件

• -prune 不在指定的目录中查找

• -user 按照文件属主查找

• -group 按照文件所属组进行查找

• -mtime -n +n 按照文件的更改时间来查找

• -nogroup 查找无有效所属组的文件

• -nouser 查找无效属主的文件

• -type 查找某一类型的文件– b块设备文件

– d目录

– c字符设备

– p管道文件

– l符号链接

– f普通文件114Shell 编程

Page 46: Shell 编程 - CAS

find命令选贤

• -depth 先查找当前目录中的文件再查找子目录

• -fstype 查找位于某一类型文件系统中的文件

• -mount 查找文件时不跨越mount点

• -follow 如果遇到符号链接,就跟踪至原文件

• -size n[c] 查找长度为n块的文件,c时为字节长度

115Shell 编程

Page 47: Shell 编程 - CAS

find选项例子

• 使用name选项– find . –name “*.txt” –print

• 使用perm选项– find . –perm 755 –print

• 忽略某个目录– find /apps –path“/apps/bin”-prune –o –print

• 使用user和nouser选项– find ~ -user dave –print

– find /home –nouser -print116Shell 编程

Page 48: Shell 编程 - CAS

find 选项例子

• 按照更改时间查找文件– find / -mtime -5 –print

• 使用type选项– find /etc –type d -print

• 使用-size选项 (查找大于1M的文件)– find . –size +1000000c –print

• 使用depth选项– find / -name “a.out” –depth -print

117Shell 编程

Page 49: Shell 编程 - CAS

使用exec或者ok来执行shell命令

• exec后紧跟要执行的命令,然后是一对{},一个空格和一个\

• find . –type f –exec ls –l {} \;

– 该例子中find匹配到了当前目录下所有的普通文件,并在-exec选项中使用了ls –l 将它们列出

• find /logs –type f –mtime +5 –exec rm {} \;

– 在logs目录下查找更改时间在5日以前的文件并删除之

– 使用删除时,建议使用-ok选项而实现交互功能

118Shell 编程

Page 50: Shell 编程 - CAS

find命令实战

• find . -type f -perm 4755 –print

• find / -type f -size 0 -exec ls -l {} \;

• find /var/logs -type f -mtime +7 -exec rm {} \;

• find /-name -group audit -print

• find . -type d -print -local -mount |sort

119Shell 编程

Page 51: Shell 编程 - CAS

xargs

• 解决find和-exec搭配使用时报参数列太长的错误

• 使用xargs可以一次获取所有参数,也可以分批获取参数

• find / -type –f –print | xargs file

• find /apps/audit -perm -7 -print | xargs chmod o-w

120Shell 编程

Page 52: Shell 编程 - CAS

正则表达式

• 匹配行首和行尾

• 匹配数据集

• 只匹配字母和数字

• 匹配一定范围内的字符串集

121Shell 编程

Page 53: Shell 编程 - CAS

基本元字符集

122Shell 编程

Page 54: Shell 编程 - CAS

使用句点匹配单字符

• 句点可以匹配任意单字符– beg.n 匹配以beg开头,中间夹一个任意字符

– ls –l中匹配一定的权限 …x..x..x• drwxrwxrw- -no match

• -rw-rw-rw- -no match

• -rwxrwxr-x -match

– ….XC…. 前4个字符之后是XC,前4个后四个任意• 1234XC9088 -match

• 4523XX9001 -no match

– “.”允许匹配ASCII集中任意字符123Shell 编程

Page 55: Shell 编程 - CAS

在行首以^匹配字符串

• ^只允许在一行的开始匹配字符和单词

• ls –l匹配目录– ^d

• drwxrwxrw- -match

• -rw-rw-rw- -no match

• ^comp..ing– 行首为comp,后面紧跟2个任意字符,并以

ing结尾

124Shell 编程

Page 56: Shell 编程 - CAS

在行尾以$匹配字符串或字符

• $与^相反,在行尾匹配字符串

• 匹配以trouble结尾的所有行– trouble$

• 匹配所有空行– ^$

• 匹配只有一个字符的行– ^.$

125Shell 编程

Page 57: Shell 编程 - CAS

使用*匹配字符串中的单字符或其重复序列

• compu*t 将匹配字符u 0次或者多次– computer

– computing

– compuuuuute

126Shell 编程

Page 58: Shell 编程 - CAS

使用\屏蔽特殊字符

• 特殊字符:– $ . ’”* [ ] ^ | ( ) \ + ?

127Shell 编程

Page 59: Shell 编程 - CAS

使用[ ]匹配一个范围或集合

• 可用逗号将[ ]内不同字符串分开

• 使用-表示一个字符串范围

• 匹配任意一个数字

– [0123456789]

– [0-9]

• 匹配任意字母

– [a-zA-Z]

• 匹配任意字母或数字

– [a-zA-Z0-9]

128Shell 编程

Page 60: Shell 编程 - CAS

使用[ ]匹配一个范围或集合

• 匹配Computer和computer两个单词– [Cc]omputer

• 匹配以字母o或u开头,后跟一个字符任意次,并以t结尾的任意单词– [ou].*t

• 匹配所有单词– [A-Za-z]*

• 匹配任一非字母型字符– [^a-zA-Z]

• 匹配任一非数字型字符– [^0-9]

129Shell 编程

Page 61: Shell 编程 - CAS

使用\{\}匹配模式出现的次数

• pattern\{n\} 匹配模式出现n次

• pattern\{n,\} 匹配模式至少出现n次

• pattern\{n,m\} 匹配模式出现次数n到m之间

• A \{2\}B 匹配值为AAB

• A\{4,\}B 匹配A至少4次 AAAAB AAAAAAB

• [0-9]\{4\}XX[0-9]\{4\}– 匹配数字出现4次,后跟代码XX,最后数字出现4次

– 4523XX9001

130Shell 编程

Page 62: Shell 编程 - CAS

经常使用的正则表达式

131Shell 编程

Page 63: Shell 编程 - CAS

经常使用的正则表达式

132Shell 编程

Page 64: Shell 编程 - CAS

• 文本过滤

133Shell 编程

Page 65: Shell 编程 - CAS

主要内容和学习要求

能够熟练运用 grep命令

掌握 sed流编辑器

学会使用 awk编程

134Shell 编程

Page 66: Shell 编程 - CAS

grep是 Linux 下使用最广泛的命令之一,其作用

是在一个或多个文件中查找某个字符模式所在的行,并

将结果输出到屏幕上。

grep命令不会对输入文件进行任何修改或影响

grep 家族

grep家族由 grep、egrep和 fgrep组成:

grep:标准 grep命令,主要讨论此命令。

egrep:扩展 grep,支持基本及扩展的正则表达式。

fgrep:固定 grep (fixed grep),也称快速 grep ( fast

grep ),按字面解释所有的字符,即正则表达式中的元字符不会被特殊处理。

这里的“快速”并不是指速度快。135Shell 编程

Page 67: Shell 编程 - CAS

grep 命令的一般形式

grep [选项] pattern file1 file2 ...

grep -f patternfile file1 file2 ...

grep 的使用

pattern:可以是正则表达式(用单引号括起来)、

或字符串(加双引号)、或一个单词。

file1 file2 ... :文件名列表,作为 grep命令的输入;grep的输

入也可以来自标准输入或管道;

可以把匹配模式写入到一个文件中,每行写一个,然

后使用 -f选项,将该匹配模式传递给 grep 命令

136Shell 编程

Page 68: Shell 编程 - CAS

-c 只输出匹配的行的总数

-i 不区分大小写

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

-l 查询多个文件时,只输出包含匹配模式的文件的文

件名

-n 显示匹配的行及行号

-v 反向查找,即只显示不包含匹配模式的行

-s 不显示错误信息

grep –i 'an*' datafile

grep 常用选项

137Shell 编程

Page 69: Shell 编程 - CAS

grep 命令应用丼例

查询多个文件,可以使用通配符 “ *”

grep "math2" *.txt

grep "12" *

反向匹配

ps aux | grep "ssh" | grep –v "grep"

匹配空行

grep -n '^$' datafile

grep -v '^$' datafile > datafile2138Shell 编程

Page 70: Shell 编程 - CAS

精确匹配单词: \< 和 \>

grep 'west\>' datafile

grep '\<north' datafile

grep '\<north\>' datafile

grep 命令应用丼例

找出所有包含 以 north 开头 的单词的行

找出所有包含 以 west 结尾 的单词的行

找出所有包含 north 单词的行

139Shell 编程

Page 71: Shell 编程 - CAS

递归搜索目录中的所有文件:-r

grep -r "north" datafile ~/Teaching/linux/

关于某个字符连续出现次数的匹配

grep 'o\{2,\}' helloworld

'o\{2,4\}' , 'o\{2,4\}' , 'lo\{2,4\}'

grep 命令应用丼例

140Shell 编程

Page 72: Shell 编程 - CAS

其它

grep '^n' datafile

grep 'y$' datafile

grep 'r\.' datafile

grep '^[we]' datafile

grep –i 'ss*' datafile

grep –n '[a-z]\{9\}' datafile

grep –c '\<[a-z].*n\>' datafile

grep 命令应用丼例

141Shell 编程

Page 73: Shell 编程 - CAS

ls –l | grep '^d'

如果传递给 grep 的文件名参数中有目录的话,需使用 “ -d ” 选项

grep -d [ACTION] directory_name

其中 ACTION 可以是read:把目录文件当作普通文件来读取skip:目录将被忽略而跳过recurse:递归的方式读取目录下的每一个文件,可以用选项 "-r" 代替"-d recurse"

grep -rl "eth0" /etc

grep 与管道

142Shell 编程

Page 74: Shell 编程 - CAS

使用 egrep的主要好处是,它在使用 grep提供

的正则表达式元字符基础上增加了更多的元字符,见

下表,但不能使用 \{ \}。

egrep 增加的元字符

在 Linux下:egrep = grep -E

egrep 命令

+ 匹配一个或多个前一字符

? 匹配零个或一个前一字符

str1|str2 匹配 str1或 str2

( ) 字符组

注意星号 * 和问号 ? 在 shell 通配符和正则表达式中的区别143Shell 编程

Page 75: Shell 编程 - CAS

egrep 'WE+' datafile

egrep 'WE?' datafile

egrep 'Sh|u' datafile

egrep 'S(h|u)' datafile

fgrep命令

fgrep的使用方法与 grep类似,但对正则表达式中的任何元字符都不

做特殊处理。

fgrep '^n' datafile

egrep 丼例与 fgrep

144Shell 编程

Page 76: Shell 编程 - CAS

sed 是一个精简的、非交互式的编辑器,它在命令行中输入编辑命令和指定

文件名,然后在屏幕上查看输出。

sed是什么

sed如何工作sed逐行处理文件(或输入),并将输出结果发送到屏幕。

即:sed从输入(可以是文件或其它标准输入)中读取一行,将之拷贝到一个编

辑缓冲区,按指定的 sed编辑命令进行处理,编辑完后将其发送到屏幕上,然后

把这行从编辑缓冲区中删除,读取下面一行。重复此过程直到全部处理结束。

sed只是对文件在内存中的副本进行操作,所以 sed 不会修改输入文件的内容。

sed总是输出到标准输出,可以使用重定向将 sed的输出保存到文件中。

流编辑器 sed

145Shell 编程

Page 77: Shell 编程 - CAS

在命令行中直接调用sed [-n][-e] 'sed_cmd' input_file

-n:缺省情况下,sed 在将下一行读入缓冲区之前,自动输

出行缓冲区中的内容。此选项可以关闭自动输出。

-e:允许调用多条 sed 命令,如:

sed -e 'sed_cmd1' -e 'sed_cmd2' input_file

sed_cmd:使用格式: [address]sed_edit_cmd (通常用

单引号括起来),其中 address 为 sed 的行定位模式,用于指

定将要被 sed 编辑的行。如果省略,sed 将编辑所有的行。

sed_edit_cmd 为 sed 对被编辑行将要进行的编辑操作。

sed 的三种调用方式

input_file:sed 编辑的文件列表,若省略,sed 将从标

准输入(重定向或管道)中读取输入。 146Shell 编程

Page 78: Shell 编程 - CAS

sed [选项] -f sed_script_file input_file

将 sed 命令插入脚本文件,生成 sed可执行脚本

文件,在命令行中直接键入脚本文件名来执行。

#!/bin/sed -f

sed_cmd1

... ...

例:sed –n –f sedfile1 datafile

例:./sedfile2.sed -n datafile

sed 的三种调用方式

将 sed 命令插入脚本文件,然后调用

147Shell 编程

Page 79: Shell 编程 - CAS

n 表示第 n行

$ 表示最后一行

m,n 表示从第 m行到第 n行

/pattern/ 查询包含指定模式的行。如 /disk/、/[a-z]/

/pattern/,n 表示从包含指定模式的行到 第 n行

n,/pattern/ 表示从第 n行 到 包含指定模式的行

/模式1/,/模式2/ 表示从包含模式1到 包含模式2的行

!反向选择,如 m,n!的结果与 m,n相反

sed_cmd中 address的定位方式

定位方式

148Shell 编程

Page 80: Shell 编程 - CAS

p :打印匹配行

sed -n '1,3p' datafile // ('1,3!p')

sed -n '$p' datafile

sed -n '/north/p' datafile

=:显示匹配行的行号

sed -n '/north/=' datafile

d:删除匹配的行

sed -n '/north/d' datafile

常用的 sed_edit_cmd

常用 sed 编辑命令

149Shell 编程

Page 81: Shell 编程 - CAS

a\:在指定行后面追加一行或多行文本,并显示添加的

新内容,该命令主要用于 sed脚本中。

sed -n '/eastern/a\newline1\

newline2\

newlineN' datafile

i\:在指定行前插入一行或多行,并显示添加的新内容,

使用格式同 a\

c\ :用新文本替换指定的行,使用格式同 a\

l:显示指定行中所有字符,包括控制字符(非打印字符)

sed -n '/west/l' datafile

常用 sed 编辑命令

150Shell 编程

Page 82: Shell 编程 - CAS

s:替换命令,使用格式为:

sed -n 's/west/east/gp' datafile

address :如果省略,表示编辑所有的行。

g :全局替换

p :打印被修改后的行

w fname :将被替换后的行内容写到指定的文件中

sed -n 's/Aanny/Anndy/w newdata' datafile

sed 's/[0-9][0-9]$/&.5/' datafile

&符号用在替换字符串中时,代表 被替换的字符串

常用 sed 编辑命令

[address]s/old/new/[gpw]

151Shell 编程

Page 83: Shell 编程 - CAS

r:读文件,将另外一个文件中的内容附加到指定行后。

sed -n '$r newdata' datafile

w:写文件,将指定行写入到另外一个文件中。

sed -n '/west/w newdata' datafile

n:将指定行的下面一行读入编辑缓冲区。

sed -n '/eastern/{n;s/AM/Archie/p}' datafile

对指定行同时使用多个 sed编辑命令时,需用大括号 “ {} ” 括起来,命令之间

用分号 “ ; ” 格开。注意与 -e选项的区别

常用 sed 编辑命令

152Shell 编程

Page 84: Shell 编程 - CAS

q:退出,读取到指定行后退出 sed。

sed '/east/{s/east/west/;q}' datafile

p 打印匹配行 s 替换命令

= 显示匹配行的行号 l 显示指定行中所有字符

d 删除匹配的行 r 读文件

a\ 在指定行后面追加文本 w 写文件

i\ 在指定行前面追加文本 n 读取指定行的下面一行

c\ 用新文本替换指定的行 q 退出 sed

常见的 sed 编辑命令小结

常见的 sed 编辑命令小结

153Shell 编程

Page 85: Shell 编程 - CAS

在 sed_cmd中可以使用 shell变量,此时应使用 双引号

myvar= "west"

sed –n "/${myvar}/p" datafile

如何输入控制字符,如:回车、Esc、F1 等

以输入 回车 ( ^M ) 为例:

先按 Ctrl+v,释放按下的两个键后,按下对应的功能键 ( Enter键 ) 即

可。

sed支持 shell变量的使用

shell 变量的使用

154Shell 编程

Page 86: Shell 编程 - CAS

'/north/p' 打印所有包含 north的行

'/north/!p' 打印所有不包含 north的行

's/\.$//g' 删除以句点结尾的行中末尾的句点

's/^ *//g' 删除行首空格(命令中 ^ *之间有两个空格)

's/ */ /g' 将连续多个空格替换为一个空格

命令中 */前有三个空格,后面是一个空格

'/^$/d’ 删除空行

's/^.//g' 删除每行的第一个字符,同 's/.//'

's/^/%/g' 在每行的最前面添加百分号 %

'3,5s/d/D/' 把第 3行到第 5行中每行的 第一个 d改成 D

一些 sed 行命令集

155Shell 编程

Page 87: Shell 编程 - CAS

awk是一种用于处理数据和生成报告的编程语言

awk可以在命令行中进行一些简单的操作,也可以被写成脚本来处理较大的

应用问题

awk与 grep、sed结合使用,将使 shell 编程更加容易

Linux下使用的 awk是 gawk

awk是什么

awk逐行扫描输入 ( 可以是文件或管道等 ),按给定的模式查找出匹配的行,

然后对这些行执行 awk命令指定的操作。

awk如何工作

与 sed一样,awk 不会修改输入文件的内容。

可以使用重定向将 awk的输出保存到文件中。

awk 介绍

156Shell 编程

Page 88: Shell 编程 - CAS

在命令行键入命令:

awk [-F 字段分隔符] 'awk_script' input_file

若不指定字段分隔符,则使用环境变量 IFS 的值 ( 通常为空格 )

将 awd命令插入脚本文件 awd_script,然后调用:

将 awk命令插入脚本文件,生成 awk可执行脚本文件,

然后在命令行中直接键入脚本文件名来执行。

#!/bin/awk -f

awk_cmd1

... ...

awk 的三种调用方式

awk -f awd_script input_file

157Shell 编程

Page 89: Shell 编程 - CAS

awk_script可以由一条或多条 awk_cmd组成,每条 awk_cmd各占一行。

awk 'BEGIN {actions}

/pattern1/{actions}

......

/patternN/{actions}

END {actions}' input_file

awk_cmd中的 /pattern/和 {actions}可以省略,但不能同时省略;

/pattern/省略时表示对所有的输入行执行指定的 actions;{actions}省

略时表示打印匹配行。

awk 的三种调用方式

每个 awk_cmd由两部分组成:/pattern/{actions}

awk命令的一般形式:

其中 BEGIN {actions}和 END {actions}是可选的

注意 BEGIN

和 END都是

大写字母。

158Shell 编程

Page 90: Shell 编程 - CAS

⑦ 如果输入是文件列表,awk 将按顺序处理列表中的每个文件。

awk 的执行过程① 如果存在 BEGIN ,awk 首先执行它指定的 actions

② awk 从输入中读取一行,称为一条输入记录

③ awk 将读入的记录分割成数个字段,并将第一个字段放入变量

$1 中,第二个放入变量 $2 中,以此类推;$0 表示整条记录;

字段分隔符可以通过选项 -F 指定,否则使用缺省的分隔符。

④ 把当前输入记录依次与每一个 awk_cmd 中 pattern 比较:

如果相匹配,就执行对应的 actions;

如果不匹配,就跳过对应的 actions,直到完成所有的 awk_cmd

⑤ 当一条输入记录处理完毕后,awk 读取输入的下一行,重复上

面的处理过程,直到所有输入全部处理完毕。

⑥ awk 处理完所有的输入后,若存在 END,执行相应的 actions

159Shell 编程

Page 91: Shell 编程 - CAS

awk '/Mar/{print $1,$3}' shipped

awk '{print $1,$3}' shipped

awk '/Mar/' shipped

awk 'BEGIN{print "Mon data"}/Mar/{print $1,$3}' shipped

awk '/Mar/{print $1,$3} END{print "OK"}' shipped

awk -F: -f awkfile1 employees2

awk 丼例

160Shell 编程

Page 92: Shell 编程 - CAS

① 使用正则表达式:/rexp/,如 /^A/、/A[0-9]*/

awk中正则表达式中常用到的元字符有:

^ 只匹配行首 ( 可以看成是行首的标志 )

$ 只匹配行尾 ( 可以看成是行尾的标志 )

* 一个单字符后紧跟 *,匹配 0个或多个此字符

[ ] 匹配 []内的任意一个字符 ( [^]反向匹配 )

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

. 匹配任意单个字符

str1|str2 匹配 str1或 str2

+ 匹配一个或多个前一字符

? 匹配零个或一个前一字符

( ) 字符组

awk中的模式(pattern)匹配

模式匹配

161Shell 编程

Page 93: Shell 编程 - CAS

② 使用布尔 ( 比较 ) 表达式,表达式的值为真时执行相应的操作 (actions)

表达式中可以使用变量 ( 如字段变量 $1,$2等 ) 和 /rexp/

表达式中的运算符有

关系运算符: < > <= >= == !=

匹配运算符: ~ !~

x ~ /rexp/ 如果 x匹配 /rexp/,则返回真;x!~ /rexp/ 如果 x不匹配 /rexp/,则返回真。

awk '$2 > 20 {print $0}' shipped

awk '$4 ~ /^6/ {print $0}' shipped

模式匹配

162Shell 编程

Page 94: Shell 编程 - CAS

expr1 && expr2 两个表达式的值都为真时,返回真

expr1 || expr2 两个表达式中有一个的值为真时,返回真

!expr 表达式的值为假时,返回真

awk '($2<20)&&($4~/^6/){print $0}' shipped

awk '($2<20)||($4~/^6/){print $0}' shipped

awk '!($4~/^6/){print $0}' shipped

awk '/^A/ && /0$/{print}' shipped

注:表达式中有比较运算时,一般用圆括号括起来

复合表达式:&& ( 逻辑与 )、|| ( 逻辑或 )、! ( 逻辑非 )

模式匹配

163Shell 编程

Page 95: Shell 编程 - CAS

awk中的字段分隔符可以用 -F选项指定,缺省是空格。

awk '{print $1}' datafile2

awk –F: '{print $1}' datafile2

awk -F'[ :]' '{print $1}' datafile2

重定向与管道

awk '{print $1, $2 > "output"}' datafile2

awk 'BEGIN{"date" | getline d; print d}'

字段分隔符

字段分隔符、重定向和管道

164Shell 编程

Page 96: Shell 编程 - CAS

操作由一条或多条语句或者命令组成,语句、命令之间用分号 “ ;” 隔开。

操作中还可以使用流程控制结构的语句

awk 命令

exit:使 awk停止执行而跳出。若存在 END语句,则执行 END指定的

actions

AWK 中的操作 ACTIONS

print输出列表:打印字符串、变量或表达式,输出列表中各参数之间用逗号

隔开;若用空格隔开,打印时各输出之间没有空格

printf ( [格式控制符], 输出列表 ) :格式化打印,语法与 C语言中的printf函数类似

next:停止处理当前记录, 开始读取和处理下一条记录

nextfile:强迫 awk停止处理当前的输入文件而处理输入文件列表中的下

一个文件

165Shell 编程

Page 97: Shell 编程 - CAS

直接赋值:如果值是字符串,需加双引号。

awk 'BEGIN

{x=1;y=x;z="OK";

print "x=" x, "y=" y, "z=" z}'

用表达式赋值:

数值表达式: num1 operator num2

其中 operator 可以是 +, -, *, /, %, ^

当 num1 或 num2 是字符串时,awk 视其值为 0

条件表达式: A?B:C 当A为真时表达式的值为 B,否则为 C

awk 也支持以下赋值操作符:+=, -=, *=, /=, %=, ^=, ++, --

awk语句:主要是赋值语句

AWK 语句

166Shell 编程

Page 98: Shell 编程 - CAS

if (expr) {actions}

[else if {actions}] ( 可以有多个 else if语句 )

[else {actions}]

while (expr) {actions}

do {actions} while (expr)

for (init_val;test_cond;incr_val) {actions}

break:跳出 for,while 和 do-while循环

continue:跳过本次循环的剩余部分,

直接进入下一轮循环

流控制结构举例:awkfile2

awk中的流控制结构 ( 基本上是用 C 语言的语法 )

流控制

167Shell 编程

Page 99: Shell 编程 - CAS

在 awk_script中的表达式中要经常使用变量。awk的变量基本可以分为:

字段变量,内置变量和自定义变量。

字段变量:$0, $1, $2, ...

可以创建新的输出字段,比如:当前输入记录被分割为 8个字段,这时可以

通过对变量 $9 ( 或 $9之后的字段变量 ) 赋值而增加输出字段,NF的值也将随

之变化。

awk '{$6=3*$2+$3; print}' shipped

AWK 中的变量

在 awk执行过程中,字段变量的值是动态变化的。但可以修改这些字段变量的值,被修改的字段值可以反映到 awk的输出中。

字段变量支持变量名替换。如 $NF表示最后一个字段

168Shell 编程

Page 100: Shell 编程 - CAS

ARGC:命令行参数个数 ( 实际就是输入文件的数目加 1 )

ARGIND:当前被处理的文件在数组 ARGV 内的索引

ARGV:命令行参数数组

FILENAME:当前输入文件的文件名

FNR:已经被 awk 读取过的记录(行)的总数目

FS:输入记录的字段分隔符 (缺省是空格和制表符 )

NF:当前行或记录的字段数

NR:对当前输入文件而言,已被 awk 读取过的记录 ( 行 ) 的数目

OFMT:数字的输出格式 ( 缺省是 %.6g )

OFS:输出记录的字段分隔符 (缺省是空格 )

ORS:输出记录间的分隔符 (缺省是 NEWLINE )

RS:输入记录间的分隔符 (缺省是 NEWLINE )

用于存储 awk工作时的各种参数, 这些变量的值会随着 awk程序的运行而动态

的变化,常见的有:

内置变量

169Shell 编程

Page 101: Shell 编程 - CAS

在表达式中出现不带双引号的字符串都被视为变量

自定义变量

变量定义 varname = value

变量名由字母、数字和下划线组成,但不能以数字开头

awk变量无需声明,直接赋值即完成变量的定义和初始化

awk变量可以是数值变量或字符串变量

awk可以从表达式的上下文推导出变量的数据类型

如果自定义变量在使用前没有被赋值,缺省值为 0

或 空字符串

170Shell 编程

Page 102: Shell 编程 - CAS

awk '{if ($3 < ARG) print}' ARG=30 shipped

var可以是 awk内置变量或自定义变量。

var的值在 awk开始对输入的第一条记录应用 awk_script前传入。如果在awk_script中已经对某个变量赋值,那么命令行上的赋值无效。

在 awk脚本程序中不能直接使用 shell的变量。

可以向 awk可执行脚本传递变量的值,与命令行类似,即

awk_ex_script var1=val1 var2=val2 ... files

cat /etc/passwd | awk 'BEGIN {FS=":"} {if

($1==user) {print}}' user=$USER

如何向命令行 awk 程序传递变量的值

变量传递

awk 'awk_script' var1=val1 var2=val2 ... files

171Shell 编程

Page 103: Shell 编程 - CAS

① 常见 awk 内置数值函数

int(x):取整数部份,朝 0的方向做舍去。

sqrt(x):正的平方根。

exp(x):以 e为底的指数函数。

log(x):自然对数。

sin(x)、cos(x):正弦、余弦。

atan2(y,x):求 y/x的 arctan值,单位是弧度。

rand():得到一个随机数 ( 平均分布在 0和 1之间 )

srand(x):设定产生随机数的 seed为 x

AWK 内置函数

172Shell 编程

Page 104: Shell 编程 - CAS

② 常见 awk 内置字符串函数

index(str,substr):返回子串 substr 在字符串 str 中第

一次出现的位置,若找不到,则返回值为 0

awk 'BEGIN{print index("peanut","an")}'

awk 'BEGIN{print match("hello",/l[^l]/)}'

内置字符串函数

sprintf(format,exp1,...):返回一个指定格式的表达式,

格式 format 与 printf 的打印格式类似 ( 不在屏幕上输出 )

match(str,rexp): 返回模式 rexp 在字符串 str 中第一次出

现的位置,如果 str 中不包含 rexp,则返回值 0

length(str):返回字符串 str 的字符个数

173Shell 编程

Page 105: Shell 编程 - CAS

sub(rexp,sub_str,target):在目标串 target 中寻找第

一个能够匹配正则表达式 rexp 的子串,并用字符串 sub_str

替换该子串。若没有指定目标串,则在整个记录中查找

awk 'BEGIN{str="water,water";sub(/at/,"ith",str);\

print str}'

substr(str,start,len):返回 str 的从指定位置

start 开始长度为 len 个字符的子串,如果 len 省略,则返回

从 start 位置开始至结束位置的所有字符。

awk 'BEGIN{print substr("awk sed grep",5)}'

内置字符串函数

gsub(rexp,sub_str,target):与 sub 类似,但 gsub 替

换所有匹配的子串,即全局替换。

174Shell 编程

Page 106: Shell 编程 - CAS

awk 'BEGIN{split("11/15/2005",date,"/"); \

print date[2]}'

awk 'BEGIN{print tolower("MiXeD CaSe 123")}'

内置字符串函数

split(str,array,fs):使用由 fs 指定的分隔符将字符串

str 拆分成一个数组 array,并返回数组的下标数

tolower(str):将字符串 str 中的大写字母改为小写字母

toupper(str):将字符串 str 中的小写字母改为大写字母

175Shell 编程

Page 107: Shell 编程 - CAS

③ 常见 awk 内置系统函数

close(filename)

将输入或输出的文件 filename关闭。

system(command)

此函数允许调用操作系统的指令,执行完毕后返回 awk

awk 'BEGIN {system("ls")}'

内置系统函数

176Shell 编程

Page 108: Shell 编程 - CAS

function fun_name (parameter_list) {

body-of-function

// 函数体,是 awk语句块

}

parameter_list是以逗号分隔的参数列表

自定义函数可以在 awk程序的任何地方定义

函数名可包括字母、数字、下标线,但不可以数字开头

调用自定义的函数与调用内置函数的方法一样

awk '{print "sum =", SquareSum($2,$3)} \

function SquareSum(x,y) { \

sum=x*x+y*y ; return sum \

}' shipped

AWK 的自定义函数

177Shell 编程

Page 109: Shell 编程 - CAS

数组使用前,无需预先定义,也不必指定数组元素个数

访问数组的元素

for (element in array_name ) print \

array_name[element]

经常使用循环来访问数组元素

awk 'BEGIN{print \

split("123#456#789",mya,"#"); \

for (i in mya) {print mya[i]}}'

AWK 中的数组

178Shell 编程

Page 110: Shell 编程 - CAS

使用字符串或正则表达式时,有时需要在输出中加

入一新行或一个特殊字符。这时就需要字符串屏蔽。

\b 退格键 \t tab键

\f 走纸换页 \n 新行

\r 回车键 \ddd 八进制值 ASCII码

\c 任意其他特殊字符。如: \\为反斜线符号

awk 中常用的字符串屏蔽序列

awk 'BEGIN{print \

"\nMay\tDay\n\nMay\t\104\141\171"}'

字符串屏蔽

179Shell 编程

Page 111: Shell 编程 - CAS

基本上和 C 语言的语法类似

printf( [格式控制符], 参数列表 )

参数列表中可以有变量、数值数据或字符串,用逗号隔开

格式控制符:%[-][w][.p]fmt

%:标识一个格式控制符的开始,不可省略

-:表示参数输出时左对齐,可省略

w:一个数字,表示参数输出时占用域的宽度,可省略

.p:p是一个数值,表示最大字符串长度或小数位位数,可省略

fmt:一个小写字母,表示输出参数的数据类型,不可省略

AWK 输出函数 PRINTF

180Shell 编程

Page 112: Shell 编程 - CAS

c ASCII字符 d 整数

f 浮点数,如 12.3 e 浮点数,科学记数法

g 自动决定用 e或 f s 字符串

o 八进制数 x 十六进制数

常见的 fmt

echo "65" | awk '{ printf "%c\n",$0 }'

awk 'BEGIN{printf "%.4f\n",999}'

awk 'BEGIN{printf \

"2 number:%8.4f %8.2f",999,888}'

AWK 输出函数 PRINTF

181Shell 编程

Page 113: Shell 编程 - CAS

为了避免碰到 awk 错误,要注意以下事项:

确保整个 awk_script用单引号括起来

确保 awk_script内所有引号都成对出现

确保用花括号括起动作语句,用圆括号括起条件语句

如果使用字符串,要保证字符串被双引号括起来

( 在模式中除外 )

awk 语言学起来可能有些复杂,但使用它来编写一行命令或小脚本并不太难。

awk是 shell编程的一个重要工具。在shell命令或编程中,可以使用 awk强

大的文本处理能力。

注意事项

182Shell 编程