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查到的默认权限为002.所以可以推断出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=valueenv查看
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<<delimiter                                     ---输入直到delimiter分解符
command<filename                                       ----输入文件内容到命令
command<-
                                                     --- 关闭标准输入
>nullfile.txt                                                       ---创建字节为0的文件
command1<filename>command3               ---按从左到右顺序执行
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<<exit
> 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
注意:如果从文件中读入变量<filename要放到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<NR;i++){print i,name[i]}}' donors

(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包含合法参数的值,即带:的参数后跟的参数值

 

你可能感兴趣的:(linux,shell编程学习)