shell用法总结
shell基础的一些东西
●umask --查看当前用户创建文件或文件夹时的默认权限
[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
总结:
规律:如果文件权限位=7-umask-1 目录权限位=7-umask
●连接ln
硬连接 ln sourcefile targetfile 连接后的target文件大小和source文件一样,如果删除文件,必须硬链接数为0时,才表示真正的删除
软连接 ln -s sourcefile targetfile 类似于windows的快捷方式
●shell script 基本结构
#!/bin/bash --------bash shell开头必须部分
# description --------注释部分(可有可无,为了阅读方便最好加以说明)
variable name=value ---------变量部分,声明变量,赋值
control segment ---------流程控制结构,如判断、循环、顺序
#创建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查看后台运行的脚本,输出信息重定向到nohup.out,以追加的形式
⑤重定向 >,< 可以改变程序运行的输出来源和输入来源
⑥变量 可以用$varname 来调用变量
⑦特殊字符
`用来替换命令
\用来使shell无法认出其后的特殊字符,使其失去特殊含义
;允许一行放多个命令
() 创建成组的命令
{} 创建命令块
关于变量和运算符:
●本地变量:在用户现在的shell生命期的脚本中使用。设置变量:various_name=value.可用set 来查看。用readonly可以使变量只读。
●环境变量:用于当前用户下所有用户进程(不限于现在的shell)。
设置变量:export various_name=value。用env查看。
用readonly可以使变量只读。
●变量替换
echo ${variablename} 显示实际值到variablename
echo ${variablename:+value} 如果设置了variablename,则显示value值,否则为空
echo ${variable name:?value} 如果未设置variablename,则显现用户定义错误信息value
echo ${variablename:-value} 如果未设置variablename,则显示value,否则显示variablename
echo ${variablename:=value} 如果未设置,则设置其值,并显示,若已经设置,则只是显示
●清除变量 unset variable name
●位置变量
位置变量表示$0,$1,$2...$9
$0 ----脚本名字
$1 ----根据参数位置表示参数1
#! /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 -path
PS2 --一命令多行,换行提示 二级提示符,一行命令没有全部输出,换行后的提示符,,如>
PWD --当前目录
MAILCHECK --每隔多少秒检查是否有新邮件
[test@szbirdora 1]$ echo $MAILCHECK
60
SHELL --当前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 创建整数变量
使用+替代-,可以颠倒选项的含义,比如调试时用的比较多的set -x开启调试信息,set +x 关闭调试信息
export
-p 显示全部全局变量
shift[n] 移动位置变量,调整位置变量,使$3赋予$2,使$2赋予$1 n 前移n,比如shift 1 ,就是原来属于$1的变成$2,$2的变成$3
typeset 和declare同义
注意:双引号不能解析$,\,`三个字符,所以在双引号中可以引用变量、转义字符、替换变量
比如 echo -e "$var \t `ls -l`" 如果需要echo支持转义字符需要加-e选项
单引号可以解析,所以单引号中引用变量等无效
[test@szbirdora 1]$ echo "$test"
test
[test@szbirdora 1]$ echo '$test'
$test
●运算符类型
⒈按位运算符
~ 取反
<< 左移运算符
>> 右移运算符
& 与
| 或
^ 异或
$[ ] 表示形式告诉shell对方括号中表达式求值 $[a+b]
2.逻辑运算符
&&
||
>,<,=,!=
3.赋值运算符
let variablename1=variablename1+ varablename2
let variablename1 +=variablename1
关于 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 2>&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]$ cat >>myfile<<exit
> China
> Hubei
> Suizhou
> exit
从标准输入读到exit为止,并追加输入到myfile
[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
从文件中按照行读数据 #!/bin/bash #while02 while read LINE do echo $LINE done < names.txt
注意:如果从文件中读入变量<filename要放到done后
#!/bin/bash #while02 #这样写是不对的 ,需要把<name.txt 放在 while循环后面 while read LINE < names.txt do echo $LINE 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'{} \;' 注意{}和\;之间的空格 如 :find ./ -name "*.sh" -exec ls -l {} \;
-ok 与-exec相同,不过执行命令前会有提示
options :
-name
-perm
-user
-group
-mtime -n +n (atime,-ctime) 修改时间(访问时间,创建时间)+n超过n天,-n为n天以内
-size n:[c] 查找文件长度为n块的文件,带有c时表示文件长度以字节计。
-depth:在查找文件时,首先查找当前目录中的文件,然后再在其子目录中查找。默认就支持
-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 选项含义
--version 显示sed版本。
--help 显示帮助文档。
-n,--quiet,--silent 静默输出,默认情况下,sed程序在所有的脚本指令执行完毕后,将自动打印模式空间中的内容,这些选项可以屏蔽自动打印。
-e script 允许多个脚本指令被执行。
-f script-file,
--file=script-file 从文件中读取脚本指令,对编写自动脚本程序来说很棒!
-i,--in-place 直接修改源文件,经过脚本指令处理后的内容将被输出至源文件(源文件被修改)慎用!
-l N, --line-length=N 该选项指定l指令可以输出的行长度,l指令用于输出非打印字符。
--posix 禁用GNU sed扩展功能。
-r, --regexp-extended 在脚本指令中使用扩展正则表达式
-s, --separate 默认情况下,sed将把命令行指定的多个文件名作为一个长的连续的输入流。GNU sed则允许把他们当作单独的文件, 这样如正则表达式则不进行跨文件匹配。
-u, --unbuffered 最低限度的缓存输入与输出。
基本sed命令
p 打印匹配行
= 显示文本行号
a 在定位行号后附加新文本信息
i 在定位行号前插入新文本信息
d 删除定位行
c 用新文本替换定位文本
s 使用替换模式替换相应模式
r 从另一个文件中读文本
w 写文本到一个文件
q 第一个模式匹配完成后退去
l 显示与八进制ascii代码等价的控制字符
{} 在定位行执行命令组
n 从一个文件中读文本下一行,并附加在下一行
g 将模式2粘贴到/pattern n/
y 传送字符
这里就简单介绍几个脚本指令操作作为sed程序的例子。
a,append 追加
i,insert 插入
d,delete 删除
s,substitution 替换
sed基本语法结构
sed Options... [script] [inputfile...]
sed 选项... [脚本指令] [输入文件]
如果没有输入文件,则sed默认对标准输入进行处理(即键盘输入)。脚本指令是第一个不以“-”开始的参数。
1.选项含义:
查找替换应用举例 sed '2a TYPE=Ethernet' test.txt 第二行后添加TYPE=Ethernet sed '3i TYPE=Ethernet' test.txt 第三行前添加TYPE=Ethernet sed 's/yes/no/g' test.txt 将样本文件中的所有yes替换为no sed '3,4d' test.txt 删除第3至4行的内容 总结:以上大多数操作指令,都依据行号定位操作对象(地址),如:2a即第二行后添加。 但实际情况可能大多数情况你并不确定你要操作对象(地址)的行号,这时更多的我们会使用正则表达式确定操作对象(地址)。
下面是使用正则表达式定位操作行的示例: sed '/222/a iiii=1111 ' testfile.txt 匹配到包含222的行,并在其后添加iiii=1111 sed '/^aaa/d' testfile.txt 匹配以aaaa开始的行,并删除改行
需要执行多个指令时,可以使用以下三种方法: #sed 's/yes/no/;s/static/dhcp/' test.txt 注:使用分号隔开指令。
#sed -e 's/yes/no/' -e 's/static/dhcp/' test.txt 注:使用-e选项。 #sed ' >s/yes/no/ >s/static/dhcp/' test.txt 注:利用分行指令。 然而在命令行上输入过长的指令是愚蠢的,这时就需要-f选项指定sed脚本文件,在脚本文件中可以包含多行指令,而且便于修改!
sed -i 's/^M//g' a.txt > new.out (-i选项是会直接修改源文件的,慎用) cat gpdata_wbm10.bak | sed 's/^M//g' | awk '$0' > 2.log
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
删除第二行并且把c替换成d
sed命令r ---从文件中读取选定的行,读入输入文件中,显示在匹配的行后面
eg.
[test@szbirdora 1]$ cat 11
*******************Alaska***************
[test@szbirdora 1]$ sed '/a/r 11' myfile
a
*******************Alaska***************
b
c
d
e
从myfile中匹配a的行并把文件11的内容放到a的后面并输出到标准输出
写入命令:w 将输入文件中的匹配行写入到指定文件中
eg.
[test@szbirdora 1]$ cat 11
b
[test@szbirdora 1]$ sed -n '/a/w 11' myfile
[test@szbirdora 1]$ cat 11
a
就是把myfile中匹配到的a写入到11文件中,原来文件11的内容会被清空
追加:a 将文本追加到匹配行的后面。sed要求在a后加\,不止一行的以\连接
eg.
[test@szbirdora 1]$ sed '/b/a\****************hello*************\-------------china---------' myfile
a
b
****************hello*************-------------china---------
c
d
e
在b的后面追加但不写入文件
插入命令: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
插入到b前面,不修改文件
下一个: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 '{if($1~"Tom") print $1,$2}'
可见awk用法比较灵活
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)}'
NF 就是字段数,NR就是已经读取的记录数
具体可以查看这个博客
https://blog.csdn.net/qq_34685846/article/details/73224709
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
|后用""关闭管道
至于sort请看这个博客:
http://blog.51cto.com/lspgyy/1282334
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
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% /
即把myfile文件内容每两行分割成以split命名开头的文件
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,$1 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
| Column 1 | Column 2 | Column 3 |
| -------- | -------- | -------- |
| Text | Text | Text |
optind初始值为1,在optgets处理完一次命令行参数后加1
optarg包含合法参数的值,即带:的参数后跟的参数值
添加用户和组
如下可知:
user是王五:只有读权限
组是g88:读写执行
当切换到itcast代表为other用户,对文件a,c只有执行权限
切换到wangwu,代表当前用户为王五,有读权限
当然也可以如下设置