首页 > 代码库 > linux shell脚本编写

linux shell脚本编写

大家好

    这是一篇自己阅读、学习的shell编程,工作中大量应用,尤为awk、sed、grep为主。希望对大家速成有用

可以直接翻看到中部位置

【data】

export PATH=/mall/jdk/jdk1.7/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin

export LANG=zh_CN.GB18030


start=`date +%s -d "2011-11-28 15:55:37"`

end=`date +%s -d "2011-11-28 15:55:52"`

echo $(($end-$start)) 

date "+%Y-%m-%d %H:%M:%S"

date -d ‘+1 day‘ +"%d"   本日+1

date -s 20100405

date -s 14:31:00


1、上个月末

date -d `date +%y%m01`"-1 day" +%d

2、往前倒

date -d -`date +%d`day +%d

3、条件

if [`date +%d -d tomorrow` == 01 ];

4、上个月

date -d last-month

date -d -1month

date -d ‘-1 month‘ +"%m"

5、下个月

date -d next-month

date -d 1month

6、本月初

date -d 1`date +%B`

上个月初

date -d 1`date -d last-month +%B`

指定月份

day -d 1May


echo `date +%d` | xargs -I{} date -d ‘-{} day‘ +%Y%m%d       Linux如何得到上月月末日期



sed -i "3s/.*/$table/g" conf/run.sql 

table=t_sms_mt_log_`date +"%m"`    本月,然后月初1号还是统计上月

date -d ‘-1 day‘ +"%m"             本月,实实在在的本月

subject="每日验证码下发数量统计_`date -d ‘-1 day‘ +"%m%d"`"


select * from t_sys_user where user_code=‘duanzz‘;


update  t_sys_user set terminal_id=‘13730000000‘ where user_code=‘duanzz‘;



set fileformat=unix


字符串的截取-替换

echo ${stringa:1}    从第二位一直往后所有

echo ${stringa:2:5}  从第三位往后一共截取5位


echo ${stringZ:(-4)}  从右到左开始截取

echo ${stringZ: -4}   从右到左开始截取,和上面效果一样

a=${stringa%%f}       去掉变量stringa后缀f。

echo ${stringZ/abc/xyz}  变量中字符串   abc被xyz替换

echo ${stringZ/#abc/XYZ} 用‘XYZ‘替换开头的‘abc‘.

echo ${stringZ/%abc/XYZ} 用‘XYZ‘替换结尾的‘abc‘.


you_id=${USER}-on-${HOSTNAME}  

you_id=$USER\-on-$HOSTNAME  

echo $you_id  root-on-db1  效果一样。变量与字符串混合输出

val=${1##+(0)} # 使用局部变量, 匹配最长连续的一个或多个0.



引用:${backup_DIR}/$DATE

#备份的变量:

backup_dir=/home/mysql/mysql_bak

date=`date -d "+%Y%m%d %H:%M:%d"`

yes_time=`date -d yesterday  "+%Y%m%d"`

mkdir -p /opt/chen$date\nailong    chen20160608nailong

date -d "2 day ago" +"%Y-%m-%d"    昨天日期

date -d "1 week ago" +"%Y-%m-%d"   上周日期 

date +%Y%m%d%h%M


单引号(‘ ‘)操作与双引号基本一样, 但是不允许引用变量, 因为$的特殊意义被关闭了. 在单引号中,

任何特殊字符都按照字面的意思进行解释, 除了‘. 所以说单引号("全引用")是一种比双引号("部分引

用")更严格的引用方法.



‘‘ 单引号屏蔽所有特殊字符

"" 双引号屏蔽部分特殊字符


【eval】


两次扫描


test.txt内容:hello shell world!


myfile="cat test.txt"


(1)echo $myfile  #result:cat test.txt


(2)eval echo $myfile  #result:hello shell world!


【echo】

echo -e 处理特殊字符,解释特殊字符。生效特殊字符

echo -n 不换行输出

echo -e "a\ndddd" //自动换行

echo $(ls -al)不换行             echo "$(ls -al)" 换行


bash$ echo hello\!

hello!

bash$ echo "hello\!"

hello\!

bash$ echo -e x\ty

xty

bash$ echo -e "x\ty"

x y


echo "chen" >> file :把chen内容追加到file文件中来,不覆盖

echo "chen" > file :覆盖了!!!



[A-Za-z0-9]


########################  (( ... ))结构可以用来计算并测试算术表达式的结果.

#!/bin/bash

((5 > 4))

echo $?

echo "Exit status of \"((5 > 4))\" is $?."


【从键盘输入-不止是read】

command << word

any input

word



read -p "Your command: " CMD

until [ $CMD == ‘q‘ ]; do

   ! which $CMD && echo "Wrong command" && read -p "Input again:" CMD && continue

  COMMAND=` which $CMD | grep -v "^alias" | grep -o "[^[:space:]]\{1,\}"`

  bincp $COMMAND

  echo "copy $COMMAND finished."

  read -p "Continue: " CMD

done


【输出到屏幕上】

cat << word

-----------

name     id

word

【脚本中调用】 source _function.sh

【shell函数】

hello ()

{

echo `date`

}

hello    ###这儿直接写hello

`反引号允许你将shell命令的输出赋值给变量 

today=`date +%Y%m%d`

echo "today is `date +%Y%m%d`"


sleep 5 #过五秒再执行



【basename】

$ basename /tmp/test/file.txt

file.txt

$ basename /tmp/test/file.txt .txt

file


【dirname】

dirname /var/log/messages   获取文件或文件夹的路径(上一级)

/var/log


【数组】

var=("123" "456" "789")

var[1]=123

var[2]=456

echo "$var[1],$var[2]"

#


echo $?  条件为真,输出0,条件为否,输出1

cp 1.txt /opt/apps/2.txt >/dev/null 2>&1

status=$?

echo $?   #如果cp这个命令成功的话,输出0,不成功的话,输出1


:冒号在此是占位符,{str:=expr} 如果变量str不为空,${str:=expr}就等于str的值,若str为空,就把expr的值赋值给str

: >> target_file  如果这个文件之前并不存在, 那么就创建它

if [ $name="" ] 如果这个变量为空值

then : # 什么都不做,引出分支.

if [ ! -s 22.txt ] 如果22.txt这个文件为空

或者是 if [ -z 22.txt ]


  [ $I -eq 1 ] && MIN=$MYRAND

  

if [ -s $name ] 如果这个变量为空

if [ -d $path ] 如果目录存在

if [ -s $path ] 如果目录存在

if [ -n "$1" ]  # 测试是否有命令行参数(非空).

     -a 文件存在     YES !

     -f 这是一个一般文件

     -d 这是一个目录

     -b 这是一个快设备(软盘,硬盘,光驱等)

     -c 这是一个字符设备(键盘,声卡等)

     -p 这个文件是一个管道

     -h 或者 -L 这是一个符号链接

     -r 文件是否可读

     -w 文件是否可写

     -x 文件是否可执行

     -O 你是否为文件拥有者

     -G 文件group-id是否与你相同

f1 -nt f2 文件f1比文件f2新

f1 -ot f2 文件f1比文件f2旧




&&:and    |:或者  !:非     command||comand  ||:前者命令为真,后者才能执行,否则后者不执行

comand&&comand 前者为真,后者执行,前者为假,后者略过

sort:排序  wc:统计

cd /opt && ./1.txt    :逐次执行的

【查找内存使用情况】

[root@db1 opt]# free -m|grep Mem|awk ‘{print "used\n----"};{print $3}‘

used

----

985


【数值比较】

------------在 [ ] 中使用

-eq 数值相等。

-ne 数值不相等。

-gt 第一个数大于第二个数。

-lt 第一个数小于第二个数。

-le 第一个数小于等于第二个数。

-ge 第一个数大于等于第二个数。

------------在 (( )) 中使用 

<=       >   <   >=

----------字符串比较   =   ==


小于, 按照ASCII字符进行排序

if [[ "$a" < "$b" ]]

if [ "$a" \< "$b" ]

注意"<"使用在[ ]结构中的时候需要被转义.


-a    逻辑与   exp1 -a exp2     如果表达式exp1和exp2都为真的话, 那么结果为真.

-o    逻辑或   exp1 -o exp2     如果表达式exp1和exp2中至少有一个为真的话, 那么结果为真.

if [ "$exp1" -a "$exp2" ]


与(逻辑)

1 if [ $condition1 ] && [ $condition2 ]

2 # 与 if [ $condition1 -a $condition2 ] 相同

3 # 如果condition1和condition2都为true, 那结果就为true.

4

5 if [[ $condition1 && $condition2 ]] # 也可以.

6 # 注意: &&不允许出现在[ ... ]结构中.


或(逻辑)

1 if [ $condition1 ] || [ $condition2 ]

2 # 与 if [ $condition1 -o $condition2 ] 相同

3 # 如果condition1或condition2中的一个为true, 那么结果就为true.

4

5 if [[ $condition1 || $condition2 ]] # 也可以.

6 # 注意||操作符是不能够出现在[ ... ]结构中的.





【grep】 

经常跟cat使用:  cat /path/filename |grep [option] 

grep -i 忽略大小写 

grep -v "^#"   file   :grep -v "^#" filename 输出头字符不为#的行

grep -o 只显示匹配的字符串

grep --color 输出时,查找的关键字带颜色。

grep ‘[nN]*‘ test1.sh

grep -C 5 foo file 显示file文件里匹配foo字串那行以及上下5行

grep -B 5 foo file 显示foo及前5行

grep -A 5 foo file 显示foo及后5行


精准匹配  grep ‘:80\b‘  只匹配到 :80

netstat -nat|grep ‘:80\>‘

netstat -nat|grep ‘:80\b‘

grep -E ‘123|abc‘ filename  // 找出文件(filename)中包含123或者包含abc的行




【sed】


-r 支持正则表达式


sed -n ‘5p‘ filename  选择第5行输出

sed -n ‘/^\//p‘ /etc/fstab  sed出以/开头的行并且print出来

sed ‘/^\/dev/d‘ fstab  查找以/dev开头的行删除

sed ‘s/^L/#/g‘ fstab_bak   把fstab_bak中L开头的行,把L换成#   加g表示全局替换


sed -n ‘/^\//a hello‘ /etc/fstab  sed出以/开头的行并且随后追加一行:hello进去并且print出来,a的作用是追加,给文件追加内容

sed -n ‘/^\//a hello \n chen‘ /etc/fstab 再添加一行chen 这是给后面添加行,如果是前面添加   把a换位i


sed ‘3r /etc/fstab‘ fstab_bak 在fstab_bak的第三行处添加etc/fstab的内容进来

sed ‘/tmp/w /etc/tmp.txt‘ /etc/fstab 讲fstab有tmp的行保存在/etc/tmp.txt文件中来


sed ‘1,3d‘ /etc/fstab 删除第一行和第三行

sed ‘1,+2d‘ /etc/fstab 删除第一行以及以下两行

sed -e ‘8/p‘ -e ‘s/30/50/g‘ 1.txt  多个命令执行

sed ‘/^F/=‘ 1.txt  首字符为F的,并且输出他 的行号

sed ‘/chen/s/x/X/g‘ passwd   找到passwd中chen那一行,并且在那一行将x改为X

sed -n ‘/^#/!{/chen/p}‘ 11.txt    查找首字母不为#的且包含chen的行。打印出来

sed -i ‘/chen/{s/^#//g}‘ 11.txt   包含chen,并且首字符为#,去掉#。生效

sed -i ‘/^#/d‘ a.txt  去除空行

sed ‘/^chen/s/^chen.*/CHENNAILONG/‘ install.log   把chen开头的行整行替换为CHENNAILONG

sed -i "7s/.*/$table/g" conf/run.sql    把第七行替换为$table变量的值

sed ‘s/<!--/&chen/‘ 1.txt     在<!--后面追加  chen 

\   转译特殊字符

cat tomcat_running_state.txt |sed -r ‘s/\s+/\n/1‘   第一个空格替换为换行


BASHUSERS=`echo $BASHUSERS | sed ‘s@[[:space:]]@,@g‘`


xargs的默认命令是echo,这意味着通过管道传递给xargs的输入将会包含换行和空白,不过通过xargs的处理,换行和空白将被空格取代。


sed的后向引用;待研究

如果想sed命令生效  可加上-i


sed -f /path/script /etc/fstab  去这个目录选找script下面的所有脚本,对fstab进行处理


sed -i ‘s/^[[:space:]]//g‘ /etc/fastab 去fstab下,把行首的空格去掉  [[:space"]]+ 至少一个空格





【awk】


~  匹配正则表达式        <    小于    ==不包含,必须等于

~!不匹配正则表达式      !==  不等于  &&两边都为真  |或者||    !非

awk ‘{print $1,$4}‘ fstab_bak  awk出第一列与第四列

awk ‘{print $1"\t"$4}‘ fstab_bak  awk出第一列与第四列,输出时候,中间加上空格

awk ‘{if($1~/devpts/)}print{$2}‘ fstab_bak  如果第一列出现devpts,这打印devpts的第二列内容

awk ‘{if($1~/devpts/)}print{ "good"}‘ fstab_bak  如果第一列出现devpts,这打印出good

awk ‘{if($1<$2)}{print $0}‘ fstab_bak 如果第一列中的数字小于第二列中的数字,输出这一行

awk ‘{$1~/^...a/}‘ fstab_bak  第一列中如果有第三字符为a的

awk ‘{$1~/tmpfs|proc/}‘ fstab_bak 第一列有tmpfs或者proc的,输出出来

awk -F "," ‘{print $2}‘ q.txt 以","为分隔符,找出第二段并且输出

awk ‘{name=$1;belts=$4;if(belts ~/yellow/)print name "is belt" belts}‘ grant.txt

awk ‘{if($1~"chen")($1="chennailong");print $1}‘ 1.txt 第一列中有chen出现,chen替换为chennailong

awk ‘{if($1~/chen/) {($1="chennailong");print $1}}‘ 1.txt 上条命令输出所有,多一对{}代表输出只修改那一行

awk ‘{if($1~/chen/){print $0}}‘ 1.txt 

awk ‘{sum+=$2};{print sum}‘ 1.txt 统计第二列的总和

ls -al | awk ‘ /^[^d]/ {print $9"\t"$5} {tot+=$5} END {print "total KB:"tot}‘ 统计此目录下文件的文件名和长度,以及总和

awk ‘BEGIN {split("123#456#789",myawk,"#")}‘ 给字段123#456#789切分,以#为分隔符

awk -F! ‘{print substr($3,6,11)}‘ 1.txt 截取以!为分隔符的第三段的第6字符以及包括第六字符往后11字符,如果只有6,那就是6个地附后往后这个行所有的了

awk ‘sub(/chen/,"chen",$1)‘ 1.txt 截取第一段(默认分隔符为空格),含有chen的,替换为CHEN

awk ‘BEGIN {ST="chen is a good boy"} END {print substr(ST,1,4)}‘ 1.txt 定义一个变量叫ST,然后使用substr截取第一字符以及包括第一字符往后4字符

awk ‘BEGIN {ST=$1} END {print substr($1,1,4)}‘ 1.txt 

awk ‘BEGIN {ST=$1} END {print substr($1,1,4)}‘ 1.txt |sed ‘/ST/p

awk ‘{print length($0)}‘   计算字符串长度

num=$(awk -F! ‘{print substr($3,6,11)}‘ 1.txt)   赋值。。。 有点意外吧

echo $num

awk ‘{print NR}‘ filename 统计一下此文件总共多少行

awk ‘{print NF}‘ filename 统计一下此文件总共多少域

awk ‘{if (NR > 0 && $4~/chen/) print$0}‘ filename 打印不为空行,并且第四列包含chen的行 

awk -F: {‘print $1‘} /etc/passwd|tr "\n" " "  #查找passwd里面的用户,这么多用户横向输出出来

echo $PWD |awk -F/ ‘{print $NF}‘ 显示其目录

awk -F ‘"‘   特殊字符



who |awk ‘{if($1~/root/);print $1"\t""welcome"}‘

who |awk ‘{print $1"\t""welcome"}‘

【wc】

wc -l | file 计算行数

wc -w | file 计算文件中单词数

wc -c 。。。。字符数

【cut】

cut -b 3 :取第三列(无分隔符)

cat 1.txt |cut -d! -f1 以!为分隔符,切出第一段输出

cat 1.txt |cut -d! -f2-3 以!为分隔符,切出第一段与第三段输出

           cut -c1  cut -c1-5 按照字符切割

【find】

find /etc -perm 777 -print

find /etc -type |xargs -exec ls -al {}\;  -exec只用在find出文件时候使用     

find -type f  

find /etc -user chen -print

find /etc -size +1G -print.

find /etc -mtime -n(距今多少天) +n(多少天前)

find ./ -name "*.txt" -delete

find ./ -name "*.txt" |xargs rm -rf

find ./ -name "*.txt" -exec {} rm \;

【sort】

sort passwd  默认排序

sort -t passwd

sort -t: -k1 passwd 按照:分隔符排序,k1是表示第一域。表示按照用户名排序了。

sort -n -k 2 这是按照数字排序,表示按照第二列的数字排序

cat access.log |awk ‘{print $1}‘ |sort |uniq -c |sort -n -r |head -n 10

awk ‘{print $1}‘ access.log|sort | uniq -c |sort -n -k 1 -r|more

sort -u (去除重复行,排序)  sort -r(降序) sort -r file.log -o file.log(排序后重定向)

sort -n number。log (字符型,升序排序)  

【head】

head -n 10 一般经过排序后,统计选取前10 或者 head -10

tail -n 10 统计后10   tail -1000 acess.log

【uniq】

uniq -c 打印每一重复行的次数:基本上是统计ip什么的访问次数-----用的最多


uniq -d 只显示有重复数据行,并且重复行只显示其中一行



【脚本练习】-------【if else判断】

#!/bin/bash

echo "give Y is ok; gei N is no"

read choose

echo "your action is $choose"

if [ "$choose" == "Y" ]

then

    echo "your choose is yes,thanks"

elif [ "$choose" == "N" ]

then 

    echo "your choose is no,we are sorry to you"

else

    echo "take your answer in [Y]or[N]"

fi


【if】

if [ "$UID" -ne "$ROOT_UID" ]  # 当然要使用root用户来运行. 下列为判断 不为root时候   

if [ -n "$1" ]                 # 测试是否有命令行参数(非空).


if cd "$dir" 2>/dev/null; then # "2>/dev/null" 会隐藏错误信息.

与此相似, 在中括号中的条件判断也不一定非得要if不可, 也可以使用列表结构.

var1=20

var2=22

[ "$var1" -ne "$var2" ] && echo "$var1 is not equal to $var2"

home=/home/bozo

[ -d "$home" ] || echo "$home directory does not exist."



【expr】 


用于整数值,也可用于字符串

expr 10 + 10    输出20 

expr  30 / 3    输出10

expr  30 \* 3   输出90


【case】

case $name in 

root) echo "welcome super user"

;;

chen) echo "welcome chen"

;;

*) echo "unknown words"

;;

esac

【for循环】

for $name in chen root ni   #这里面是条件,如果什么满足什么

do 

echo $name               #如条件成立,则输出操作

done


for i in *.txt;do mv $i $(sed "s/txt/sh/" <<<$i);done  把所有txt文件改为sh文件

for I in {1..100}20.



【until】  until循环不断挂起,直至文件22.txt被删除,删除后,脚本进入正常状态

#!/bin/bash

file=/opt/22.txt

until [ ! -f $file ]


do


 sleep 1

done

echo "file deleted"


【while】while简单循环  count小与5,则继续+1.档不满足小与5时。输出此时count的值

#!/bin/bash

count=0

while [ "$count" -lt 5 ]

do

count=`expr $count + 1`

echo $count

done


【split】文件有6行,切割为每2行为一个文件,一共切出3个文件。依次为xaa xab xac

split -2 a.txt


也可以 while read name  键盘输入


【tr】一般进行替换或者删除,进行字符转换

tr -s "[a-z]" < a.txt  表示去除重复字母   例如homeeeeee变为home

tr -s "[\012]" <a.txt 或者 tr -s "["\n"]" <a.txt 删除空行

tr -s "[a-z]" "[A-Z]" <a.txt  将小写转换为大写

tr -s "[chen]" "[chennailog]" <a.txt 将chen替换为chennailing


cat 201601.csv|awk -F ‘,‘ ‘{print $1}‘ |sort|uniq -c|sort -rn|awk ‘{if ($1>1);print $2}‘|xargs -i grep {} 201601.csv


如果这一行的第一列=另外一行的第一列,输出这一整行


 export TMOUT=0  终端永不超时,直接在上面 不会exit

 


ROOT_UID=0   # $UID为0的时候,用户才具有root用户的权限

LINES=50     # 默认的保存行数

E_XCD=66     # 不能修改目录?

E_NOTROOT=67 # 非root用户将以error退出



linux shell脚本编写