shell 编程 - cas
TRANSCRIPT
Shell 编程
曙光信息产业有限公司
技术支持中心
Index
• The shell of Linux
• Bourne Shell Programming
• find.and.regular.expression
• text manipulation
2Shell 编程
The shell of Linux
• Bourne shell (sh),
• C shell (csh),
• Korn shell (ksh),
• TC shell (tcsh),
• Bourne Again shell (bash)
3Shell 编程
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 编程
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 编程
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 编程
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 编程
• Bourne Shell Programming
Shell 编程 75
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 编程
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
Bourne Shell Programming
• Control structures– if … then
– for … in
– while
– until
– case
– break and continue
Shell 编程 78
if … then
• Structure
if test-command
then
commands
fi
Example:
if test “$word1” = “$word2”
then
echo “Match”
fi
79Shell 编程
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 编程
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 编程
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 编程
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 编程
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 编程
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 编程
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 编程
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 编程
if…then…elif
• Structureif test-command
thencommands
elif test-commandthen
commands...
elsecommands
fi
88Shell 编程
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 编程
for… in
• Structurefor loop-index in argument_listdo
commandsdone
Example:for file in *do
if [ -d “$file” ]; thenecho $file
fidone
90Shell 编程
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 编程
while
• Structure
while test_command
do
commands
done
Example:
while [ “$number” –lt 10 ]
do
… …
number=`expr $number + 1`
done
92Shell 编程
until
• Structureuntil test_commanddo
commandsdone
Example:secretname=jennyname=nonameuntil [ “$name” = “$secretname” ]do
echo “ Your guess: \c”read name
done
93Shell 编程
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 编程
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 编程
case
• Structurecase test_string inpattern-1 )
commands_1;;
pattern-2 )commands_2
;;… …esac
• default case: catch all pattern* )
96Shell 编程
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 编程
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 编程
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 编程
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 编程
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 编程
Example
[ruihong@dafinn ~/cs3451]$ more inter
#!/bin/sh
trap 'echo PROGRAM INTERRUPTED' 2
while true
do
echo "programming running."
sleep 1
done
104Shell 编程
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 编程
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 编程
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 编程
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 编程
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 编程
Exercise
• Let’s look at some system scripts – /etc/init.d/syslog
– /etc/init.d/crond
110Shell 编程
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 编程
• Shell 中的find和正则表达式
112Shell 编程
使用find和xargs
• find 命令选项
• 使用find 命令不同选项的例子
• 配合find 使用xargs的例子
• find命令的一般格式– find pathname -options [-print -exec -ok]
– -print find 命令将匹配的文件输出到标准输出
– -exec find 命令对匹配到的文件执行该参数给出的shell命令,命令格式为 ‘command’{} \
113Shell 编程
find命令选项
• -name 按照文件名查找文件
• -perm 按照文件权限查找文件
• -prune 不在指定的目录中查找
• -user 按照文件属主查找
• -group 按照文件所属组进行查找
• -mtime -n +n 按照文件的更改时间来查找
• -nogroup 查找无有效所属组的文件
• -nouser 查找无效属主的文件
• -type 查找某一类型的文件– b块设备文件
– d目录
– c字符设备
– p管道文件
– l符号链接
– f普通文件114Shell 编程
find命令选贤
• -depth 先查找当前目录中的文件再查找子目录
• -fstype 查找位于某一类型文件系统中的文件
• -mount 查找文件时不跨越mount点
• -follow 如果遇到符号链接,就跟踪至原文件
• -size n[c] 查找长度为n块的文件,c时为字节长度
115Shell 编程
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 编程
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 编程
使用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 编程
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 编程
xargs
• 解决find和-exec搭配使用时报参数列太长的错误
• 使用xargs可以一次获取所有参数,也可以分批获取参数
• find / -type –f –print | xargs file
• find /apps/audit -perm -7 -print | xargs chmod o-w
120Shell 编程
正则表达式
• 匹配行首和行尾
• 匹配数据集
• 只匹配字母和数字
• 匹配一定范围内的字符串集
121Shell 编程
基本元字符集
122Shell 编程
使用句点匹配单字符
• 句点可以匹配任意单字符– 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 编程
在行首以^匹配字符串
• ^只允许在一行的开始匹配字符和单词
• ls –l匹配目录– ^d
• drwxrwxrw- -match
• -rw-rw-rw- -no match
• ^comp..ing– 行首为comp,后面紧跟2个任意字符,并以
ing结尾
124Shell 编程
在行尾以$匹配字符串或字符
• $与^相反,在行尾匹配字符串
• 匹配以trouble结尾的所有行– trouble$
• 匹配所有空行– ^$
• 匹配只有一个字符的行– ^.$
125Shell 编程
使用*匹配字符串中的单字符或其重复序列
• compu*t 将匹配字符u 0次或者多次– computer
– computing
– compuuuuute
126Shell 编程
使用\屏蔽特殊字符
• 特殊字符:– $ . ’”* [ ] ^ | ( ) \ + ?
127Shell 编程
使用[ ]匹配一个范围或集合
• 可用逗号将[ ]内不同字符串分开
• 使用-表示一个字符串范围
• 匹配任意一个数字
– [0123456789]
– [0-9]
• 匹配任意字母
– [a-zA-Z]
• 匹配任意字母或数字
– [a-zA-Z0-9]
128Shell 编程
使用[ ]匹配一个范围或集合
• 匹配Computer和computer两个单词– [Cc]omputer
• 匹配以字母o或u开头,后跟一个字符任意次,并以t结尾的任意单词– [ou].*t
• 匹配所有单词– [A-Za-z]*
• 匹配任一非字母型字符– [^a-zA-Z]
• 匹配任一非数字型字符– [^0-9]
129Shell 编程
使用\{\}匹配模式出现的次数
• 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 编程
经常使用的正则表达式
131Shell 编程
经常使用的正则表达式
132Shell 编程
• 文本过滤
133Shell 编程
主要内容和学习要求
能够熟练运用 grep命令
掌握 sed流编辑器
学会使用 awk编程
134Shell 编程
grep是 Linux 下使用最广泛的命令之一,其作用
是在一个或多个文件中查找某个字符模式所在的行,并
将结果输出到屏幕上。
grep命令不会对输入文件进行任何修改或影响
grep 家族
grep家族由 grep、egrep和 fgrep组成:
grep:标准 grep命令,主要讨论此命令。
egrep:扩展 grep,支持基本及扩展的正则表达式。
fgrep:固定 grep (fixed grep),也称快速 grep ( fast
grep ),按字面解释所有的字符,即正则表达式中的元字符不会被特殊处理。
这里的“快速”并不是指速度快。135Shell 编程
grep 命令的一般形式
grep [选项] pattern file1 file2 ...
grep -f patternfile file1 file2 ...
grep 的使用
pattern:可以是正则表达式(用单引号括起来)、
或字符串(加双引号)、或一个单词。
file1 file2 ... :文件名列表,作为 grep命令的输入;grep的输
入也可以来自标准输入或管道;
可以把匹配模式写入到一个文件中,每行写一个,然
后使用 -f选项,将该匹配模式传递给 grep 命令
136Shell 编程
-c 只输出匹配的行的总数
-i 不区分大小写
-h 查询多个文件时,不显示文件名
-l 查询多个文件时,只输出包含匹配模式的文件的文
件名
-n 显示匹配的行及行号
-v 反向查找,即只显示不包含匹配模式的行
-s 不显示错误信息
grep –i 'an*' datafile
grep 常用选项
137Shell 编程
grep 命令应用丼例
查询多个文件,可以使用通配符 “ *”
grep "math2" *.txt
grep "12" *
反向匹配
ps aux | grep "ssh" | grep –v "grep"
匹配空行
grep -n '^$' datafile
grep -v '^$' datafile > datafile2138Shell 编程
精确匹配单词: \< 和 \>
grep 'west\>' datafile
grep '\<north' datafile
grep '\<north\>' datafile
grep 命令应用丼例
找出所有包含 以 north 开头 的单词的行
找出所有包含 以 west 结尾 的单词的行
找出所有包含 north 单词的行
139Shell 编程
递归搜索目录中的所有文件:-r
grep -r "north" datafile ~/Teaching/linux/
关于某个字符连续出现次数的匹配
grep 'o\{2,\}' helloworld
'o\{2,4\}' , 'o\{2,4\}' , 'lo\{2,4\}'
grep 命令应用丼例
140Shell 编程
其它
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 编程
ls –l | grep '^d'
如果传递给 grep 的文件名参数中有目录的话,需使用 “ -d ” 选项
grep -d [ACTION] directory_name
其中 ACTION 可以是read:把目录文件当作普通文件来读取skip:目录将被忽略而跳过recurse:递归的方式读取目录下的每一个文件,可以用选项 "-r" 代替"-d recurse"
grep -rl "eth0" /etc
grep 与管道
142Shell 编程
使用 egrep的主要好处是,它在使用 grep提供
的正则表达式元字符基础上增加了更多的元字符,见
下表,但不能使用 \{ \}。
egrep 增加的元字符
在 Linux下:egrep = grep -E
egrep 命令
+ 匹配一个或多个前一字符
? 匹配零个或一个前一字符
str1|str2 匹配 str1或 str2
( ) 字符组
注意星号 * 和问号 ? 在 shell 通配符和正则表达式中的区别143Shell 编程
egrep 'WE+' datafile
egrep 'WE?' datafile
egrep 'Sh|u' datafile
egrep 'S(h|u)' datafile
fgrep命令
fgrep的使用方法与 grep类似,但对正则表达式中的任何元字符都不
做特殊处理。
fgrep '^n' datafile
egrep 丼例与 fgrep
144Shell 编程
sed 是一个精简的、非交互式的编辑器,它在命令行中输入编辑命令和指定
文件名,然后在屏幕上查看输出。
sed是什么
sed如何工作sed逐行处理文件(或输入),并将输出结果发送到屏幕。
即:sed从输入(可以是文件或其它标准输入)中读取一行,将之拷贝到一个编
辑缓冲区,按指定的 sed编辑命令进行处理,编辑完后将其发送到屏幕上,然后
把这行从编辑缓冲区中删除,读取下面一行。重复此过程直到全部处理结束。
sed只是对文件在内存中的副本进行操作,所以 sed 不会修改输入文件的内容。
sed总是输出到标准输出,可以使用重定向将 sed的输出保存到文件中。
流编辑器 sed
145Shell 编程
在命令行中直接调用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 编程
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 编程
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 编程
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 编程
a\:在指定行后面追加一行或多行文本,并显示添加的
新内容,该命令主要用于 sed脚本中。
sed -n '/eastern/a\newline1\
newline2\
newlineN' datafile
i\:在指定行前插入一行或多行,并显示添加的新内容,
使用格式同 a\
c\ :用新文本替换指定的行,使用格式同 a\
l:显示指定行中所有字符,包括控制字符(非打印字符)
sed -n '/west/l' datafile
常用 sed 编辑命令
150Shell 编程
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 编程
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 编程
q:退出,读取到指定行后退出 sed。
sed '/east/{s/east/west/;q}' datafile
p 打印匹配行 s 替换命令
= 显示匹配行的行号 l 显示指定行中所有字符
d 删除匹配的行 r 读文件
a\ 在指定行后面追加文本 w 写文件
i\ 在指定行前面追加文本 n 读取指定行的下面一行
c\ 用新文本替换指定的行 q 退出 sed
常见的 sed 编辑命令小结
常见的 sed 编辑命令小结
153Shell 编程
在 sed_cmd中可以使用 shell变量,此时应使用 双引号
myvar= "west"
sed –n "/${myvar}/p" datafile
如何输入控制字符,如:回车、Esc、F1 等
以输入 回车 ( ^M ) 为例:
先按 Ctrl+v,释放按下的两个键后,按下对应的功能键 ( Enter键 ) 即
可。
sed支持 shell变量的使用
shell 变量的使用
154Shell 编程
'/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 编程
awk是一种用于处理数据和生成报告的编程语言
awk可以在命令行中进行一些简单的操作,也可以被写成脚本来处理较大的
应用问题
awk与 grep、sed结合使用,将使 shell 编程更加容易
Linux下使用的 awk是 gawk
awk是什么
awk逐行扫描输入 ( 可以是文件或管道等 ),按给定的模式查找出匹配的行,
然后对这些行执行 awk命令指定的操作。
awk如何工作
与 sed一样,awk 不会修改输入文件的内容。
可以使用重定向将 awk的输出保存到文件中。
awk 介绍
156Shell 编程
在命令行键入命令:
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 编程
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 编程
⑦ 如果输入是文件列表,awk 将按顺序处理列表中的每个文件。
awk 的执行过程① 如果存在 BEGIN ,awk 首先执行它指定的 actions
② awk 从输入中读取一行,称为一条输入记录
③ awk 将读入的记录分割成数个字段,并将第一个字段放入变量
$1 中,第二个放入变量 $2 中,以此类推;$0 表示整条记录;
字段分隔符可以通过选项 -F 指定,否则使用缺省的分隔符。
④ 把当前输入记录依次与每一个 awk_cmd 中 pattern 比较:
如果相匹配,就执行对应的 actions;
如果不匹配,就跳过对应的 actions,直到完成所有的 awk_cmd
⑤ 当一条输入记录处理完毕后,awk 读取输入的下一行,重复上
面的处理过程,直到所有输入全部处理完毕。
⑥ awk 处理完所有的输入后,若存在 END,执行相应的 actions
159Shell 编程
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 编程
① 使用正则表达式:/rexp/,如 /^A/、/A[0-9]*/
awk中正则表达式中常用到的元字符有:
^ 只匹配行首 ( 可以看成是行首的标志 )
$ 只匹配行尾 ( 可以看成是行尾的标志 )
* 一个单字符后紧跟 *,匹配 0个或多个此字符
[ ] 匹配 []内的任意一个字符 ( [^]反向匹配 )
\ 用来屏蔽一个元字符的特殊含义
. 匹配任意单个字符
str1|str2 匹配 str1或 str2
+ 匹配一个或多个前一字符
? 匹配零个或一个前一字符
( ) 字符组
awk中的模式(pattern)匹配
模式匹配
161Shell 编程
② 使用布尔 ( 比较 ) 表达式,表达式的值为真时执行相应的操作 (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 编程
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 编程
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 编程
操作由一条或多条语句或者命令组成,语句、命令之间用分号 “ ;” 隔开。
操作中还可以使用流程控制结构的语句
awk 命令
exit:使 awk停止执行而跳出。若存在 END语句,则执行 END指定的
actions
AWK 中的操作 ACTIONS
print输出列表:打印字符串、变量或表达式,输出列表中各参数之间用逗号
隔开;若用空格隔开,打印时各输出之间没有空格
printf ( [格式控制符], 输出列表 ) :格式化打印,语法与 C语言中的printf函数类似
next:停止处理当前记录, 开始读取和处理下一条记录
nextfile:强迫 awk停止处理当前的输入文件而处理输入文件列表中的下
一个文件
165Shell 编程
直接赋值:如果值是字符串,需加双引号。
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 编程
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 编程
在 awk_script中的表达式中要经常使用变量。awk的变量基本可以分为:
字段变量,内置变量和自定义变量。
字段变量:$0, $1, $2, ...
可以创建新的输出字段,比如:当前输入记录被分割为 8个字段,这时可以
通过对变量 $9 ( 或 $9之后的字段变量 ) 赋值而增加输出字段,NF的值也将随
之变化。
awk '{$6=3*$2+$3; print}' shipped
AWK 中的变量
在 awk执行过程中,字段变量的值是动态变化的。但可以修改这些字段变量的值,被修改的字段值可以反映到 awk的输出中。
字段变量支持变量名替换。如 $NF表示最后一个字段
168Shell 编程
ARGC:命令行参数个数 ( 实际就是输入文件的数目加 1 )
ARGIND:当前被处理的文件在数组 ARGV 内的索引
ARGV:命令行参数数组
FILENAME:当前输入文件的文件名
FNR:已经被 awk 读取过的记录(行)的总数目
FS:输入记录的字段分隔符 (缺省是空格和制表符 )
NF:当前行或记录的字段数
NR:对当前输入文件而言,已被 awk 读取过的记录 ( 行 ) 的数目
OFMT:数字的输出格式 ( 缺省是 %.6g )
OFS:输出记录的字段分隔符 (缺省是空格 )
ORS:输出记录间的分隔符 (缺省是 NEWLINE )
RS:输入记录间的分隔符 (缺省是 NEWLINE )
用于存储 awk工作时的各种参数, 这些变量的值会随着 awk程序的运行而动态
的变化,常见的有:
内置变量
169Shell 编程
在表达式中出现不带双引号的字符串都被视为变量
自定义变量
变量定义 varname = value
变量名由字母、数字和下划线组成,但不能以数字开头
awk变量无需声明,直接赋值即完成变量的定义和初始化
awk变量可以是数值变量或字符串变量
awk可以从表达式的上下文推导出变量的数据类型
如果自定义变量在使用前没有被赋值,缺省值为 0
或 空字符串
170Shell 编程
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 编程
① 常见 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 编程
② 常见 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 编程
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 编程
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 编程
③ 常见 awk 内置系统函数
close(filename)
将输入或输出的文件 filename关闭。
system(command)
此函数允许调用操作系统的指令,执行完毕后返回 awk
awk 'BEGIN {system("ls")}'
内置系统函数
176Shell 编程
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 编程
数组使用前,无需预先定义,也不必指定数组元素个数
访问数组的元素
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 编程
使用字符串或正则表达式时,有时需要在输出中加
入一新行或一个特殊字符。这时就需要字符串屏蔽。
\b 退格键 \t tab键
\f 走纸换页 \n 新行
\r 回车键 \ddd 八进制值 ASCII码
\c 任意其他特殊字符。如: \\为反斜线符号
awk 中常用的字符串屏蔽序列
awk 'BEGIN{print \
"\nMay\tDay\n\nMay\t\104\141\171"}'
字符串屏蔽
179Shell 编程
基本上和 C 语言的语法类似
printf( [格式控制符], 参数列表 )
参数列表中可以有变量、数值数据或字符串,用逗号隔开
格式控制符:%[-][w][.p]fmt
%:标识一个格式控制符的开始,不可省略
-:表示参数输出时左对齐,可省略
w:一个数字,表示参数输出时占用域的宽度,可省略
.p:p是一个数值,表示最大字符串长度或小数位位数,可省略
fmt:一个小写字母,表示输出参数的数据类型,不可省略
AWK 输出函数 PRINTF
180Shell 编程
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 编程
为了避免碰到 awk 错误,要注意以下事项:
确保整个 awk_script用单引号括起来
确保 awk_script内所有引号都成对出现
确保用花括号括起动作语句,用圆括号括起条件语句
如果使用字符串,要保证字符串被双引号括起来
( 在模式中除外 )
awk 语言学起来可能有些复杂,但使用它来编写一行命令或小脚本并不太难。
awk是 shell编程的一个重要工具。在shell命令或编程中,可以使用 awk强
大的文本处理能力。
注意事项
182Shell 编程