linux base shell 基础语法2

时间:2024-09-10 23:36:50

转载 http://blog.****.net/aggrelxf/article/details/8263110

单引 双引 反引用[] [[]]

将命令的输出读入一个变量中,可以将它放入双引号中,即可保留空格和换行符(\n)

out=$(cat text.txt)

输出1 2 3

out="$(cat text.txt)"

输出:

1

2

3

--------------[]一般用于算术比较

-gt 大于

-lt 小于

-ge 大于等于

-le 小于等于

逻辑与-a

[ $var1 -eq 0 -a $var2 -gt 2 ]

逻辑或

[ $var1 -eq 0 -o $var2 -gt 2 ]

[ condition ] && action 等价于if...fi

if [ "$LOOK_OUT" -gt "85" ]

if [ -e /home/slynux ]; then

...

fi

-----------------[[]]一般用于字符串比较

if [[ -n $str1 ]] && [[ -z $str2 ]] ;

then

commands;

fi

========================

1、字符串判断

str1 = str2      当两个串有相同内容、长度时为真
str1 != str2      当串str1和str2不等时为真
-n str1        当串的长度大于0时为真(串非空) if [[ -n $1 ]]
-z str1        当串的长度为0时为真(空串)
str1         当串str1为非空时为真

2、数字的判断

int1 -eq int2    两数相等为真
int1 -ne int2    两数不等为真
int1 -gt int2    int1大于int2为真
int1 -ge int2    int1大于等于int2为真
int1 -lt int2    int1小于int2为真
int1 -le int2    int1小于等于int2为真

3 目录文件的判断(if [ ])

-r file     用户可读为真
-w file     用户可写为真
-x file     用户可执行为真
-f file     文件为正规文件为真
-d file     文件为目录为真
-c file     文件为字符特殊文件为真
-b file     文件为块特殊文件为真
-s file     文件大小非0时为真
-t file     当文件描述符(默认为1)指定的设备为终端时为真

3、复杂逻辑判断

-a         与
-o        或
!        非

  下面是一些使用实例:

#!/bin/sh
myPath="/var/log/httpd/"
myFile="/var /log/httpd/access.log"

#这里的-x 参数判断$myPath是否存在并且是否具有可执行权限
if [ ! -x "$myPath"]; then
mkdir "$myPath"
fi

#这里的-d 参数判断$myPath是否存在
if [ ! -d "$myPath"]; then
mkdir "$myPath"
fi

#这里的-f参数判断$myFile是否存在
if [ ! -f "$myFile" ]; then
touch "$myFile"
fi

#其他参数还有-n,-n是判断一个变量是否是否有值
if [ ! -n "$myVar" ]; then
echo "$myVar is empty"
exit 0
fi

#两个变量判断是否相等
if [ "$var1" == "$var2" ]; then
echo '$var1 eq $var2'
else
echo '$var1 not eq $var2'
fi

-----------------获取名称.扩展名

file_jpg="sample.jpg"

name=${file_jpg%.*}

输出sample

file_jpg="sample.jpg"

extension=${file_jpg#*.}

输出jpg

------------------ time 计算命令执行时间

time command

--------------- 重定向

0 stdin标准输入

1 stdout标准输出

2 stderr标准错误

文件打开模式:

> 等同于1> 截断模式

>>等同于1>> 追加模式

<用于从文件中读取至stdin 只读模式

ls + 2> out.txt

stdout不会有任何输出,因为错误已经重定向到out.txt中了

可以将stderr单独重定向到一个文件,将stdout重定向到另一个文件:

cmd 2>stderr.txt 1>stdout.txt

将stderr转换成stdout,使得stderr和stdout都被重定向到同一个文件:

cmd 2>&1 output.txt

或者

cmd &> output.txt

将stderr输出丢弃

some_command 2> /dev/null

将文件重定向到命令

cmd < file

向log文件中写入头部数据

#!/bin/bash

cat <<EOF>log..tt

LOG FILE HEADER

this is a test log file

EOF

-----------------------/dev/null 2>&1

*/1 * * * * root /usr/local/PHP/bin/php /var/w.php > /dev/null 2>&1

crontab内容:50 18 5-30 * * /script/myscript.sh 1> /dev/null 2>&1
其中 1> /dev/null 2>&1是什么意思??
dev/null 为系统垃圾箱
&为后台运行
但是 myscript 后面的1 和 /null后面的2 还有 &后面的1是什么意思?
1代表标准输出,2代表错误信息输出.
1>/dev/null 就是指将标准输出定向到空设备,
2>&1,的意思是将错误输出定向到和1一样的输出设备,也同样是空.

换句话说,就是不显示该程序执行过程中的任何信息

cmd >a 2>a 和 cmd >a 2>&1 为什么不同?
cmd >a 2>a :stdout和stderr都直接送往文件 a ,a文件会被打开两遍 ,由此导致stdout和stderr互相覆盖。
cmd >a 2>&1 :stdout直接送往文件a ,stderr是继承了FD1的管道之后,再被送往文件a 。a文件只被打开一遍,就是FD1将其打开
他们的不同点在于:
cmd >a 2>a 相当于使用了FD1、FD2两个互相竞争使用文件 a 的管道; 
而cmd >a 2>&1 只使用了一个管道FD1, 但已经包括了stdout和stderr。
从IO效率上来讲,cmd >a 2>&1的效率更高。

----------------- 算数运算 let expr

let 可以直接执行基本的算数操作

no1=4

no2=5

let result=no1+no2

echo $result

let no1++

let no1+=6

操作符[] ,expr 和let命令类似

result=$[ no1 + no2 ]

result=$[ $no1 + $no2 ]

result=`expr 3 + 4`

result=$(expr $no1 + 5)

---------------- 浮点运算 bc

#echo "4 * 0.56" | bc

2.24

-----------------获得字符串长度

var=123456

echo ${#var}

-----------------环境变量$PATH和export

echo $PATH

PATH通常定义在/etc/environment或/etc/profile或~/.bashrc中

export命令用来设置环境变量;

添加新的路径:

export PATH="$PATH:/home/user/bin"

或者

PATH="$PATH:/home/user/bin"

export PATH

其它环境变量:HOME,PWD,USER,UID,SHELL

查看进程相关的环境变量:

cat /proc/$PID/environ

----------------- printf 格式化输出

printf "%-5s %-10s %-4s\n" No Name Mark

printf "%-5s %-10s %-4.2f\n" 1 James 91.32

输出为:

No Name Mark

1 James 91.32

%-5s 指明了一个格式为左对齐且宽度为5的字符串替代(- 表示左对齐)

-4.2f 表示对浮点数的处理格式

-------------- 读取命令返回值$?

cmd;

echo $?;

-------------------------shell 调试

#!/bin/bash -xv 不用任何其他选项就可以启用调试功能了

sh -n sh16.sh 不执行script,仅查询语法

sh -x sh16.sh 将script执行过程全部列出来

需要给变量赋值时,可以这么写:  
变量名=值  
要取用一个变量的值,只需在变量名前面加一个$

a="hello world" 
echo "A is:" $a

//if 注意空格

a=$1

if [[ $a -eq 2 ]] ;then

echo "1"

else

echo "2"

fi

if [[ $a = gjslint ]] ;then

echo "1"

exit 0

else

echo "2"

fi

exit 0

===================== 调用php的sh

#!/bin/bash

if [[ $0 = /* ]]

then

curfile="$0"

else

curfile="$PWD/${0#./}"

fi

#得到curfile 为/usr/local/shell/automation/autoupdate_host.sh

php_path=`dirname $curfile`

#得到php_path为/usr/local/shell/automation

PHP="/usr/local/php/bin/php -q "

PROGRAM="${php_path}/clear_his.php"

#echo $PHP $PROGRAM &

$PHP $PROGRAM &

====================== [和[[有什么不同

$ type [
[ is a shell builtin
$ type [[
[[ is a shell keyword

也就是说[处理里面的字串是当作参数来处理的,而[[对待其中的字串是当作表达式来处理的 
那么当作参数和表达式有什么不同呢?

表达式中不会有wordsplitting 或者glob expansion,而参数处理会有

$ ls
file file 1 #注意是2个文件(file 和file 1)
$ (foo="file 1";[[ -f $foo ]]&&echo "$foo is a file")
file 1 is a file

]$ (foo="file 1";[ -f $foo ]&&echo "$foo is a file") # 这里file 1被分成2个word,所以出错
bash: [: file: binary operator expected

再来看看glob expansion

$ touch '*'
$ (foo="*";[ -f $foo ]&&echo "$foo is a file") #为什么显示too many arguments,因为 *被扩展为所有目录下的文件
bash: [: too many arguments
$ (foo="*";[[ -f $foo ]]&&echo "$foo is a file") # *被当成普通字符了
* is a file

参数传递中<和>会被解析成重定向符号,所以必须转义掉

$ ([ "s" < "l" ]&&echo yes) #错误使用
bash: l: No such file or directory

$ ([ "s" \> "l" ] &&echo yes) #正确使用
yes

$ ([[ "s" > "l" ]] &&echo yes) #而在表达式中比较符号不会被当作重定向符号
yes

参数传递中小括号会被分割成token,而在表达式中则会被解析成运算顺序

$ ([ "s" \> "l" -a ( file "l" \> "a" -o "l" \> "p" ) ]&&echo yes) #(和)必须被转义,以避免参数解析中的不正确分词
bash: syntax error near unexpected token `('

$ ([ "s" \> "l" -a "l""a"−o"l""p" ] &&echo yes)
yes

$ ([[ "s" > "l" && ( "l" > "a" || "l" > "p" ) ]] &&echo yes; ) #而表达式则不需要考虑这个
yes

================ shell判断文件是否存在

shell判断文件,目录是否存在或者具有权限
#!/bin/sh

myPath="/var/log/httpd/"
myFile="/var /log/httpd/access.log"

# 这里的-x 参数判断$myPath是否存在并且是否具有可执行权限
if [ ! -x "$myPath"]; then
mkdir "$myPath"
fi

# 这里的-d 参数判断$myPath是否存在
if [ ! -d "$myPath"]; then
mkdir "$myPath"
fi

# 这里的-f参数判断$myFile是否存在
if [ ! -f "$myFile" ]; then
touch "$myFile"
fi

# 其他参数还有-n,-n是判断一个变量是否是否有值
if [ ! -n "$myVar" ]; then
echo "$myVar is empty"
exit 0
fi

# 两个变量判断是否相等
if [ "$var1" = "$var2" ]; then
echo '$var1 eq $var2'
else
echo '$var1 not eq $var2'
fi

-f 和-e的区别
Conditional Logic on Files

-a file exists.
-b file exists and is a block special file.
-c file exists and is a character special file.
-d file exists and is a directory.
-e file exists (just the same as -a).
-f file exists and is a regular file.
-g file exists and has its setgid(2) bit set.
-G file exists and has the same group ID as this process.
-k file exists and has its sticky bit set.
-L file exists and is a symbolic link.
-n string length is not zero.
-o Named option is set on.
-O file exists and is owned by the user ID of this process.
-p file exists and is a first in, first out (FIFO) special file or named pipe.
-r file exists and is readable by the current process.
-s file exists and has a size greater than zero.
-S file exists and is a socket.
-t file descriptor number fildes is open and associated with aterminal device.
-u file exists and has its setuid(2) bit set.
-w file exists and is writable by the current process.
-x file exists and is executable by the current process.
-z string length is zero.

==================bash中的特殊符号

* 万用字符,代表一个或多个字符(或数字)

? 万用字符,代表一个字母

# 批注,这个最常被使用在 script 当中,视为说明!

\ 跳脱符号,将『特殊字符或万用字符』还原成一般字符

| 分隔两个管线命令的界定;

; 连续性命令的界定(注意!与管线命令并不相同)

~ 使用者的家目录

$ 亦即是变量之前需要加的变量取代值

& 将指令变成背景下工作

! 逻辑运算意义上的『非』 not 的意思!

/ 路径分隔的符号

>, >> 输出导向,分别是『取代』与『累加』

' 单引号,不具有变量置换的功能

" 具有变量置换的功能!

` ` 两个『 ` 』中间为可以先执行的指令!

( ) 在中间为子 shell 的起始与结束

[ ] 在中间为字符的组合

{ } 在中间为命令区块的组合!

exit 1:退出整个程序

--------------------dirname

dirname /home/bin/abc
得到/home/bin

------------------------- 循环读取每行 :
all_corp=sql.txt
cat $all_corp | while read line
do
echo $line
done

-----------------------整数比较

-eq 等于,如:if [ "$a" -eq "$b" ]
-ne 不等于,如:if [ "$a" -ne "$b" ]
-gt 大于,如:if [ "$a" -gt "$b" ] 
-ge 大于等于,如:if [ "$a" -ge "$b" ]
-lt 小于,如:if [ "$a" -lt "$b" ] 
-le 小于等于,如:if [ "$a" -le "$b" ]

if [ $counter -gt 1 ]; then

...

fi

< 小于(需要双括号),如:(("$a" < "$b"))
<= 小于等于(需要双括号),如:(("$a" <= "$b"))
> 大于(需要双括号),如:(("$a" > "$b"))
>= 大于等于(需要双括号),如:(("$a" >= "$b"))

---------------------------字符串比较 
= 等于,如:if [ "$a" = "$b" ]
== 等于,如:if [ "$a" == "$b" ],与=等价
注意:==的功能在[[]]和[]中的行为是不同的,如下:
1 [[ $a == z* ]] # 如果$a以"z"开头(模式匹配 )那么将为true
2 [ $a == "z*" ] # 如果$a等于z*(字符匹配 ),那么结果为true
 
3
4 [ $a == z* ] # File globbing 和word splitting将会发生
5 [ "$a" == "z*" ] # 如果$a等于z*(字符匹配),那么结果为true
一点解释,关于File globbing是一种关于文件的速记法,比如"*.c"就是,再如~也是.
但是file globbing并不是严格的正则表达式,虽然绝大多数情况下结构比较像.
!= 不等于,如:if [ "$a" != "$b" ]
这个操作符将在[[]]结构中使用模式匹配.
< 小于,在ASCII字母顺序下.如:
if [[ "$a" < "$b" ]]
if [ "$a" \< "$b" ]
注意:在[]结构中"<"需要被转义.
 
> 大于,在ASCII字母顺序下.如:
if [[ "$a" > "$b" ]]
if [ "$a" \> "$b" ]
注意:在[]结构中">"需要被转义.
具体参考Example 26-11来查看这个操作符应用的例子.
-z 字符串为"null".就是长度为0.
-n 字符串不为"null"
注意:
使用-n在[]结构中测试必须要用""把变量引起来.使用一个未被""的字符串来使用! -z
或者就是未用""引用的字符串本身,放到[]结构中。虽然一般情况下可
以工作,但这是不安全的.习惯于使用""来测试字符串是一种好习惯.

awk \'{print $2}\' class.txt | grep \'^[0-9.]\' > res

iptables 配置文件目录 /etc/sysconfig/iptables

1.别名 alias,存放位置 $HOME/.bashrc
alias ll=\'ls -lh\'
2.print=helloworld echo ${print}
3.变量:内存中一块存储单元
本地变量:登陆登出生命周期内有效,只限制于本用户
变量名=变量值
set 查看
LOCAL="TEST"
echo $LOCAL
设置变量名为只读,不能在更改,同是也不能在恢复:readonly 变量名,不能删除。

环境变量:系统变量,用于所有用户,只有环境变量才能用于所有的子进程中,本地变量不可以。
存放于/etc/profile .bash_profile
export 变量名=变量值
env或者export查看
unset 变量名 删除

变量替换:用变量的值替换变量的名
print=helloworld
echo ${print}
echo ${file1}+${file2}

--------------------位置变量:$0 $1...$9 
$0:脚本的名字 
$1:脚本的第一变量
$2:脚本的第二变量
 
向脚本中使用位置参数:./test.sh a b c

向系统命令传递参数
find /root/ -name $1 -print
./test.sh aa

标准变量:bash默认的,可以在/etc/profile中定义
EXINIT
HOME
IFS:设置分隔符,默认为空格 IFS=":"SHE
LOGNAME
MAIL 默认邮箱位置
MAILPATH多个邮箱时可以设置
TERM 显示终端类型
PS1 当前shell目录格式PS1="WANGJIAN:"
ps2 >
pwd显示当前路径 SHELL 显示当前shell
MANPATH TERMINFO

----------------------------------------------------------特殊变量
$# 变量的个数 $* 显示脚本全部参数(参数列表)

$$脚本运行的当前id号
$?显示前一个命令的运行状态

$!后台运行的最后一个进程id号 
#!/bin/bash
echo "tesh.sh"
echo "this is first variable locate:$1"
echo "this is second variable locate:$2"
echo "this is third variable locate:$3"
shift
echo "count:$#"
echo "all list:$*"
echo "pid:$$"
echo "status:$?"

./tesh.sh a b c

declare :设置或显示变量 -f只显示函数名
export:创建环境变量 -p显示所有环境变量
readonly:设置只读变量,不能修改删除
unset:取消变量的定义。-f 删除只读变量
shift:输入的位置变量改变位置 shift 表位置上移一个位置,shift 2 表上移动两个位置
双引号"":引用字符或字符串除$ \ `
单引号\'\':直接引用为字符或字符串
反引号``: 作为系统命令执行 echo `echo wangjian` wangjian
反斜杆\:转义特殊字符($*?)为普通字符
运算符:~取反 << >>移位 &与(同1为1,否0) |或(有1为1,全0为0) ^异或 逻辑运算符号&& ||
运用运算符:$[]:表示对其中的表达式求值 echo $[2+8] echo $[3&4] $[]等价于(())
[base#n] n(base>n)表示基数从2到36的任何基数 echo [10#8+1] 结果为9
let a+=3 a=a+3
表达式优先级别[] *= || && | ^ & ==
shell 的输入与输出
echo
-e 解析转义字符 echo -e "this is a bag \n\n\n"
-n 回车不换行,默认换行 echo -n "this is a cat"
转义字符(\c回车不换行 \f禁止 \t跳格相当tab \n回车换行)

read:可以从键盘或文件的某一行文本中读入信息,并将其赋给一个变量。
read varible1 varible2
如果只指定了一个变量,那么read将会把所有的输入赋给改变量,直至遇到文件结束或回车。如果多个变量,就依次赋给。shell用空格作为变量之间的分隔符。
echo -n "first name:"
read firstname
echo -n "last name:"
read lastname
echo -e "your first name :${firstname}\n"
echo -e "your last name :${lastname}\n "

read -t 5 variable 5秒钟超时
read -p "Please enter your Username: " user -p prompt 提示语
[root@ceshiji ~]#Please enter your Username:

read -s -p "Please enter your Password: " pass -s charaters are not echoed. 字符不回显示。指输入之后,不在回显

cat:显示文件内容,创建文件,还可以用它来显示控制字符
cat file1 file2 file3 同时显示
cat file1 file2 file3>myfile
cat -v dos.txt (-v 显示控制符)

管道|:一个命令的输出传给一个命令的输入
df -k|awk \'{print $1}\'|grep -v \'Filesystem\'

tee:把输出的一个副本输送到标准输出,另一个副本拷贝到相应的文件中。
tee files 在看见输出的同时,也将其存入一个文件。一般用于管道之后。
tee -a files 追加到files中 (-a 表追加)
who|tee who.out

标准输入 0
标准输出 1
标准错误 2

重定向:改变程序运行的输入来源和输出来源。
> >> < <<
command>>filename 2>&1
command <filename>filename2
cat file|sort 1 > sort.out 等价于cat file|sort > sort.out
pwd >> file.txt
>nullfile创建一个字节为零的文件 >文件名

sort < file

cat >> aa.txt << CHINAITLAB 把CHINAITLAB结尾的内容都追加到aa.txt
>HELEO ,I AM WANGJIAN
>MY NAME IS $HOME
>bye ...
>CHINAITLAB

重定向标准错误:grep \'test\' file.txt 2>error.txt
grep "test" test.txt>error.txt 2>&1 有没有错误都输入到error.txt

exec用来替代当前的shell,并没有启动子shell,而是清楚现有shell环境,重新启动一个shell
exec command
exec ./test.sh exec通常后接一个shell脚本

文件描述符
3-9可以使用 0输入 1输出 2错误
exec 3 <&0 0<name.txt 此时不会关闭当前的shell

控制流结构: if then eles case for until while break continue
if then
elif then
elif then
else
fi

if 条件1
then
语句
elif 条件2 (条件1不成立,执行条件2)
then
else (条件1 2都不成立,执行else)
语句
fi (结束)

if语句必须以单词fi终止

if $x=sedsrc;then
echo
then
echo
fi

if [ "10" -lt "12" ]

man test

echo -n "enter your name:"
read NAME
if [ "$NAME" == ""];
then
echo "you did not enter any information"
else
echo "your name is $NAME"
fi

if cp myfile.bak myfile;
then
echo "GOOD COPY"
else
echo "basename $0 :error could not copy the files" >&2

case:多选择语句。如果匹配成功,执行匹配的命令

case 值 in
模式1)
命令1
;;
模式2)
命令2
;;
esac
*表任意字符,?表任意单字符 []表范围

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
;;
esac

case $1 in
get|GET)
create_dir
get_config_file
;;
put|PUT)
put_config_file
;;
stop|STOP)
stop_server
;;
start|START)
start_server
;;
restart|RESTART)
restart_server
;;
*)
echo
echo "$Color_err Useage: ./Configure_squid.sh get|put|stop|start|restart $Color_end"
echo
exit 1
;;
esac

for
for 变量 in 列表
do
命令1
命令2
done
for语句 :提供循环执行
使用格式:
for var in values #var是变量 values是一组值
do
语句 #可以是多条语句
done
注意values的值可以全部列出,也可是通配的方式,也可以是某命令的输出值(如$(ls))。
values的值可以是:
1.列表 in 1 2 3 4 5 用空格隔开
2.文件 in file1 file2 file3
3.变量 in $a 命令输出赋值
4.命令 in `ls abc*`
5.字符串表 in "orange red blue gray"
5.特殊: 有时没有in 此时将命令行参数传入
for loop
do
find / -name $loop -print
done

[root@localhost ~]# ./sh match
/root/match
[root@localhost ~]# cat sh
#!/bin/bash
for loop
do
find /root -name $loop -print
done

#!/bin/sh
for ((i = 1; i < 254; i++)) #必须用两个括号
do
arping -I eth0 60.191.82.$i -c 1
done
arp -a > mac_table

当变量值在列表里,for循环即执行一次所有命令,使用变量名访问列表中的取值。命令可为任何有效的shell命令和语句。变量名为任意单词。in列表用法是可选的,如果不用它,for循环使用命令行的位置参数。in列表可以包含替换、字符串和文件名。
for((i=1;i<=10;i=i+1))
do
touch ar_$i;
touch full_$i;
done;

for i in {1..100}
do
.......
done

#!/bin/sh
for i in `seq 1 100`
do
echo $i
done

for loop in 1 2 3 4
do
echo $loop
done

for loop in "orange red blue grey"
do
echo $loop
done

for i in $(ls); do du -sh $i; done | sort -n 查看当前目录的大小按小--大排列

until 条件
do
命令1
命令2
...
done
条件可为任意测试条件,测试发生在循环末尾,因此循环至少执行一次.
read look
until [ "$look" ]
do
echo "full"
done

sleep 1
nohup ./test.sh &

while 命令
do
命令1
命令2
...
done

$ cat "filelist.txt"
name.txt□
txtf
□a□b□c□
$ while read file; do echo "$file"; done < "filelist.txt"
name.txt
txtf
a□b□c

echo "press ctrl+d ,stop"
while echo -n "enter a file for you like:" ; read film
do
echo " Yeah ,${file} is a good film "
done

while read line
do
echo $line
done<name.txt

break [n]:跳出循环,如果是在一个嵌入循环里,可以指定n来跳出的循环个数
continue:跳过循环步骤(本次循环)

continue只能跳过本次循环。

while :<无限循环,需要加入break跳出>

while:
do
echo -n "enter any number [1...5]"
read ANS
case $ANS in
1|2|3|4|5)
echo "you enter a number between 1 and 5"
;;
*)
echo "wrong number ,bye."
break
;;
esac
done

shift n :参数向左偏移n位。
exit :退出系统
wc -l 查看文件的行数
getopts 多参数传递
ls -R 文件夹 递归查看
iostat 1
umount -a
sync:将缓冲区的内容写到磁盘
r !date :读入日期
r 文件 从文件中读入
!pwd 执行命令 查看当前目录
r !pwd 插入当前目录
文本过滤
正则表达式:由一些字符要(元字符)组成,匹配字符串,过滤所需。
元字符:
^ :只匹配行首 $:只匹配行尾 *:匹配0个或多个此单字符
[]:只匹配[]内字符,可以是一个单字符,也可以是字符列表。可以使用-表示[]内字符序列范围,入用[1-5]代替[12345]
\:只用来屏蔽一个元字符的特殊含义 . 只匹配任意单字符,如...x..x..x
pattern\{n\}:只用来匹配前面pattern出现次数,n为次数
pattern\{n,\}:含义同上,但次数最少为n
pattern\{n,m\}:含义同上,但pattern出现次数在n与m之间.
A\{2\}B:A出现两次 AAB
A\{4,\}B:A最少出现4次,AAAAB AAAAAB
A\{2,4\}B: A出现次数范围2-4次
[0-9]\{3\}\.[0-9]\{3\}\.[0-9]\{3\}\.[0-9]\{3\}匹配ip地址
^:只允许在一行的开始匹配字符或单词.
^d
drwxrwxrw- 匹配 -rwx--x--x 不匹配
^...1
3351xc 匹配 338xcd 不匹配
$:与^相反,只允许在行尾匹配字符或字符串
trouble$
^$ :匹配空行 ^.$:匹配包含一个字符的行
*:匹配任意字符包括零个字符 如300*2 3002 匹配
\:屏蔽一个特殊字符 如* $ .
\*\.pas:匹配以*.pas结尾的所有字符或文件.
[]:匹配一个范围或集合 ,用逗号分开. 用-表示范围
[0-9] [a-z] [A-Z a-z 0-9] [S,s]

find:用来查找具有某些特征的文件的命令.遍历大的文件系统时,一般放在后台运行.

find path -options [-print -exec -ok]
-print 输出到标准输出
-exec 对匹配的文件执行该参数所给出的shell命令 形式为 command {} \; 注意{}和\;之间有空格
find . -type f -exec ls -l {} \;
find . -name "*.log" -mtime +5 rm {} \;
有时参数太长或参数列溢出,此时要用xargs 类似与exec
find / -perm -7 -print |xargs chmod o-w
find / -type f -print |xargs file

-ok 和-exec作用相同,只不过-ok以一种更安全的方式运行.
-options:
-name文件名 文件名要引号
find ./ -name "aa.txt" -print
find ./ -name "[A-Z]*" -print 大写开头的
-perm文件权限
find -perm 755 -print (路径没有表示为当前目录)
-user文件的属主
find `pwd` -user root -print
-group 文件的属组

find ./ -group root -print
-atime ctime mtime -n +n -n 表示文件更改距现在n天以内(之内),+n表示文件更改时间距现在n天以前
find 、-mtime -5 -print 修改在5天内的文件
-size n[c] 查找文件长度为n块的文件,带有c表示文件长度以字节计算
find . -size +1000000c -print 大于1000000c字节的文件
find . -size -100 小于100块的文件
-type 类型 b p c f(普通文件)
-nouser -nogroup 无属主,属组的文件 ,删除用户时产生
find / -nouser -print
find / -newer "myfile" !-newer "yourfile" -print 查找比文件myfile新比yourfile旧的文件

-depth 在子目录中查找
find . -name "aa.txt" -depth -print

grep 对文本文件进行模式查找
grep "jeny" *.txt
grep -c (只输出匹配的行数)
grep -c "aa" aa.txt
grep -n (显示匹配的行和行号)
grep -i (忽略大小写)
grep -v (反向查找)
grep -h (查询多文件时不显示文件名)
grep -H (显示文件名)
grep -s (不显示不存在或无匹配文本的错误信息)
grep "2004:22:5[0-9]" aa.txt
grep "^[^210]" myfile 不显示是210的行:包括2、1、0 打头的行

grep "\?" aa.tet 查找?

grep "[0-9]\{1,3\}.[0-9]\{1,3\}.[0-9]\{1,3\}.[0-9]\{1,3\}" qshengyang12.xml 过滤除ip地址
grep "[0-9 A-Z]\{2\}:[0-9 A-Z]\{2\}:[0-9 A-Z]\{2\}:[0-9 A-Z]\{2\}:[0-9 A-Z]\{2\}:[0-9 A-Z]\{2\}" qshengzheng12.xml过滤mac地址

grep的命令类别

[[:upper:]] 等价于[A-Z]

[[:alnum:]] 等价于[0-9 a-z A-Z]
[[:lower:]] 等价于[a-z]
[[:space:]] 等价于空格或tab键
[[:digit:]] 等价于[0-9]
[[:alpha:]] 等价于[A-Z]

service dhcpd start > /dev/null 不显示
grep "5[[:digit:]][[:digit:]]" file 在file中查找500 到599

nmap -sT ip地址
arping ip 地址

awk:是一种自解释的编程语言,可从文件或字符串中基于指定规则浏览和抽取信息。
awk脚本由各种操作和模式组成
模式和动作
模式部分决定动作语句何时触发及触发事件。(BEGIN,END)
动作对数据进行处理,放在大括号{} 内指明。(print)
分隔符号、域和记录
awk执行时,其浏览域标记为$1,$2....$n。这种方法称为域标识。$0为所有域。
注意执行时不要混淆符号$和shell提示符$,它们是不同的。
三种方式调用awk
命令方式:awk [-F filed-spearator] \'command\' input-files 用单引号 -F 来指定分隔符如 -F :
awk脚本:脚本文件
awk命令插入一个单独文件: awk -f awk-script-file input-files
awk中的$跟shell中不含义不同 $0 是所有域,$1是第一个域 ,$2是第二个域....
awk \'{print $0}\' score.txt 按行打印文件score.txt的各行.即打印所有域。
awk -F : \'{print $0}\' score.txt默认分隔符是空格,可以用-F 来指定 本例子是:
awk \'{print $1 "\t" $3}\' score.txt 打印显示第1和第3个域

awk \'BEGIN {print "num ip/n-----"} {print $1 "\t" $4} END {print "end-of-report"}\' ab.txt BEGIN和END定义了报头 num ip 打印显示第1和第4个域,最后显示end-of-report
num ip
-----
64 172.0.0.1

函数定义:shell允许将一组命名集或语句形成一个可用块,这些块称为shell函数
格式:
函数名()
{
命令1
...
}

function 函数名()
{
....
}
定义函数
#!/bin/bash
function hello ()
{
echo "hello ,today is `date`"
return 1

}
echo "this is a function test"
hello

调用:直接输入函数名
hello

参数传递到函数中
向函数传递参数就像在脚本中使用位置变量$1,$2,$3....$9
#!/bin/bash
function hello ()
{
echo "hello ,$1 today is `date`"
return 1
}
echo "this is a function test"
hello wangjian

显示: hello ,wangjian says: today is Fri Oct 12 18:05:25 csT 2007

函数文件
文件1:
#!/bin/bash
.hellofun #调入函数hellofun
echo "now going to the function hello"
hello
echo "back from the function"

文件2:
#!/bin/bash
function hello ()
{
echo "hello, today is `date`"
return 1
}

>文件名:创建大小为0的空文件

查看载入函数:set

文件1:
#!/bin/bash
.hellofun #调入函数hellofun
set
echo "now going to the function hello"
hello
echo "back from the function"
文件2:
#!/bin/bash
function hello ()
{
echo "hello, today is `date`"
return 1
}
删除函数:unset

文件1:
#!/bin/bash
.hellofun #调入函数hellofun
unset
echo "now going to the function hello"
hello
echo "back from the function"
文件2:
#!/bin/bash
function hello ()
{
echo "hello, today is `date`"
return 1
}

函数返回值:返回return的值 return 是何值就是何值。
文件1:
#!/bin/bash
.hellofun #调入函数hellofun
unset
echo "now going to the function hello"
hello
echo $?
echo "back from the function"
文件2:
#!/bin/bash
function hello ()
{
echo "hello, today is `date`"
return 1
}

awk深入学习
awk中特殊元字符 :+:表任意字符 ?:表单个字符
匹配操作符:~:匹配 !~:表示不匹配 使用:~/匹配内容/
cat score.txt|awk \'$0~/218.79.131.96/\'
awk \'$0 !~/218.79.131.96/\' score.txt
awk \'{if ($1=="218.79.131.96") print $0}\' score.txt
man awk
sed介绍
sed 选项 命令(\'\') 文件
sed不与初始化文件打交道,它操作的只是一个拷贝,然后所有的改动如果没有重定向到一个为文件,将输出到屏幕。
sed是一种重要的文本过滤工具,使用一行命令或者使用管道与grep与awk相结合
非交互性文本流编辑。
调用sed有三种方式
使用sed命令行格式为:sed [选项] sed命令 输入文件命令用\'\'刮起来
使用sed 脚本文件,格式:sed [选项] -f sed 脚本文件 输入文件
sed脚本文件 [选项] 输入文件
不管是使用shell命令行方式或脚本文件方式,如果没有指定输入文件,sed从标准输入中接受输入,一般是键盘或重定向结果。
sed命令选项
n 不打印没匹配的
c 下一命令是编辑命令
f 正在调用sed脚本文件
sed 在文件中查询文本的方式
使用行号,可以是一个简单数字,或者是一个行号范围。
使用正则表达式
x 为一行号
x,y 表示行号范围从x到y
/pattern/ 查询包含模式的行
/pattern/pattern/ 查询包含两个模式的行
pattern/,x 在给定的行号上查询包含模式的行
x,/pattern/ 通过行号和模式查询匹配行 (从x行匹配到/pattern结束)
x,y!查询不包含指定行号x和y的行
基本sed编辑命令
p:打印匹配行
=:显示文件行号
a\:在定位行号后附加新文本信息后面(分两行写)
i\:在定位行号后插入新文本信息前(分两行写)
d:删除定位行
c\:用新文本替换定位文本
s:使用替换模式替换相应模式
r:从另一个文件中读文件
w:写文本到一个文件
q:第一个模式匹配完成后推出或立即推出
l:显示与八进制ascii代码等价的控制字符
{} 在定位行执行的命令组
n 从另一个文件中读文本下一行,并附加在下一行
g 将模式2粘贴到/pattern n/
y 传送字符
例子:
sed \'2p\' aa.txt 打印第2行(其他也打印)
sed -n \'2p\' aa.txt 只打印第二行
sed -n \'1,4p\' aa.txt 只显示1-4行
sed -n \'/los/p\' aa.txt 只显示 含有los的行
sed -n \'4,/los/p\' aa.txt 只显示从第四行开始知道匹配到los为止的之间所有行
sed -n \'/^$/=\' aa.txt 只显示空行
sed -n -e \'/^$/p\' -e \'/^$/=\' aa.txt 只显示空行和空行行号(-e 表示多命令同时执行)
sed -n \'/beijing/a\/shenzhen/\' aa.txt 在beijing所在行的下一行追加shenzhen(命令从/shenzhen/\' aa.txt换行(不改变aa)输入)
sed -n \'/beijing/i\/shenzhen/\' aa.txt 在beijing所在行的前一行插入shenzhen(命令从/shenzhen/\' aa.txt换行输入)不改变aa ,但可以重定到一个文件中改变原文件)
sed -n \'/beijing/c\/shenzhen/\' aa.txt 将beijing所在行替换shenzhen(命令从/shenzhen/\' aa.txt换行输入)(不改变aa ,但可以重定到一个文件中改变原文件)

sed \'1,2d\' aa.txt 删除1和2行
sed \'s/beijing/shanghai/g\' aa.txt
sed -n \'s/china/&hello/p\' aa.txt 在匹配到china字符后追加hello
sed -n \'s/china/hello &/p\' aa.txt在匹配到china字符前追加hello
sed \'1r bb.txt\' aa.txt 在aa.txt的第一行下面插入bb.txtwenjian
sed \'/china/q\' aa.txt 匹配到第一个china就退出
sed -n \'/china/l\' aa.txt 以八进制显示
info sed man sed
sed \'/m/G\' 文件名搜索到回车加一个空行
awk \'/from/{print}\' 名打印所有含有from的行

-------------------------合并与分隔
sort 选项 files
许多不同的域按不同的列顺序分类
-c 测试文件是否已经分类
-m合并两个分类文件
-u删除所有复制行
-o 存储sort 结果的输出文件名
-t 域分隔符;用非空格或tab键分隔域
+n n为域号,使用此域号开始分类
n指定分类是域上的数字类项
-r 比较求逆
man sort

sort -c aa.txt
sort -u aa.txt 合并,有重复的行只显示第一个
sort -r aa.txt 求逆,从下向上排序
sort -t "." +2 aa.txt 分隔符为. 对第2个域进行ASCII码排序 域号从0 1 2 ..
sort -t "." +2n aa.txt 分隔符为. 对第2个域进行数字排序域号从0 1 2 ..

-----------------------uniq 选项 file
从一个文本文件中去除或禁止重复的行
-u 只先显示不重复的行
-d 只显示有重复的数据行,每种重复行只显示一行
-c 打印每一重复行出现次数
-fn n为数字,前n个域被忽略,只比较后面
man uniq

uniq -c file 查看重复次数(这里重复指的是相邻重复,隔行重复不算)
uniq -d file 只显示有重复的数据行,每种重复行只显示一行(相邻重复,隔行重复不算)
uniq -f 2 myfile.txt 前2个域被忽略,从后面的域比较
uniq -d
sort aa.txt|uniq -c 等价于 sort -u aa.txt 查看重复次数(这里重复指的是相邻重复和隔行重复)
深入讨论awk
条件操作符
~:匹配正则表达式
!~:不匹配正则表达式
&&:and
||:or
!:not
awk \'{if ($1~/^4/) print $0}\' file 如果文件file中第一个域匹配是4开头的行就全部显示
awk \'{if ($1!~/^4/) print $0}\' file 如果文件file中第一个域匹配不是4开头的行就全部显示
awk \'{if ($4~/^\[07\/jul\/2004/) print $0}\' file 打印是[07/jul/2004]开头的所有行

--------------------------awk内置变量
ARGC 命令行参数个数
ARGV 命令行参数排列
ENVIRON 支持队列中系统环境变量的使用
FILENAME awk 浏览的文件名
FNR 浏览文件的记录数
FS 设置输入域分隔符,等价于命令-F选项。
NF 浏览文件域的个数
NR 已度的记录数(行数)
OFS 输出域分隔符
ORS 输出记录分隔符
RS 控制记录分隔符
文件aa的内容为
ab#slfjslk
cd#fslkjf
df#123fjls
eb#j9sq
op#9sjtr
awk -F \'#\' \'{print NR,NF,$0}\' aa 打印行数 域数 所有记录
awk -F \'#\' \'{print ENVIRON["USER"],FILENAME, $0 ARG ARGV[0]}\' aa 打印USER环境变量,文件名,所有记录,参数个数,第一个参数。

--------------------------------字符串函数
gsub(r,s) 在整个$0中用s替代r
gsub(r,s,t)在整个t(域或记录)中s替换r
index(s,t)返回s中字符串t的第一位置
length(s)返回s的长度
match(s,r)测试s中是否包含匹配r字符串
split(s,a,fs)用fs域上将s分成序列a
sprint(fmt,exp)返回经fmt格式化后的exp
sub(r,s) 用$0中最左边最长的子串代替s
substr(s,p) 返回字符串s中从p开始的后部分
substr(s,p,n) 返回字符串s中从p开始长度为n的后部分
awk -F \'#\' \'{if(gsub("s","S",$1)) print $1}\' aa.txt 替换文件aa.txt的$1中s变成S
awk -F \'#\' \'{if(gsub("s","S")) print $0}\' aa.txt 默认是$0
awk -F \'#\' \'{print(index($2,"s")) }\' aa.txt 打印$2中s字符所在的位置。(注意是字串在前)
awk 转义字符
\b 退格键
\t tab键
\f 走纸换页
\ddd 八进制值
\n 新行
\c 任意其他特殊字符,例如\\为反斜线符号
\r 回车符
awk -F \'#\' \'{print(index($2,"s"),"\t" ,$2) }\' aa.txt

-------------------------------- printf修饰符
%c ASCII字符
%d 整数
%f 浮点数,例如(123.44)
%e 浮点数,科学记数法
%f 新行
%g awk 决定使用哪种浮点数转换e或者f
%o 八进制数
%s 字符串
%x 十六进制数
awk 数组
awk \'BEGIN {print split ("as*123",array2,"*")}\'
./awk_arry.sh grade.txt
##############
# main menu()#
##############
curdate=`date "+%Y-%m-%d %T"`
date "+%Y-%m-%d %T"显示当前日期和时间
case $a in
7)
exit
;;
*)
clear
continue
;;
esac