<?xml version="1.0" encoding="utf-8"?>
<search>
  
    
    <entry>
      <title><![CDATA[第八 面试题实战 二]]></title>
      <url>%2F2017%2F04%2F05%2FOldboy_Shell%2F8day_2%2F</url>
      <content type="text"><![CDATA[#第八 面试题实战 二@(shell脚本)[学习] [toc] 前言本章内容来自《跟老男孩学Linux运维：Shell编程实战》第19章内容第二部分 面试题12：Web及MySQL服务异常监测面试题13：监控Memcached缓存服务问题分析使用nc命令加上set/get来模拟监测 面试题14：开发脚本实现入侵检测与报警问题分析 思考过程的积累比实际代码开发能力积累更重要 什么是恶意篡改，只要是为经过许可的改动都是篡改 文件内容被改动会有如下特征 大小可能会改变 修改时间会改变 文件内容会改变，利用md5sum指纹校验 增加或删除文件，比对每次检查前后的文件数量 第一步，建立基础指纹库1find /var/html/www -type f|xargs md5sum &gt; /opt/zhiwen.db.ori 第二步，建立基础文件库1find /var/html/www -type f &gt;/opt/wenjian.db.ori 第三步，比较文件内容和文件数量变化12345md5sum -c --quiet /opt/zhiwen.db.ori#获取检测前的所有文件数量及文件名find /var/html/www -type f &gt; /opt/wenjian.db_curr.ori#比较新旧文件数量diff /opt/wenjian.db* 脚本如下:123456789101112131415161718192021222324252627#!/bin/bashRETVAL=0export LANG=enCHECK_DIR=/var/html/www[ -e $CHECK_DIR ] ||exit 1ZhiWenDbOri="/opt/zhiwen.db.ori"FileCountDbOri="/opt/wenjian.db.ori"FileCountDbCurrOri="/opt/wenjian.db_Curr.ori"ErrLog="/opt/err.log"[ -e $ZhiWenDbOri ]|| exit 1[ -e $FileCountDbOri ] || exit 1#jude file contentecho "md5sum -c --quiet $ZhiWenDbOri "&gt;$ErrLogmd5sum -c --quiet $ZhiWenDbOri &amp;&gt;&gt;$ErrLogRETVAL=$?#com file countfind $CHECK_DIR -type f &gt; $FileCountDbCurrOriecho "diff $FileCountDbCurrOri $FileCountDbOri" &amp;&gt;&gt;$ErrLogdiff $FileCountDbCurrOri $FileCountDbOri &amp;&gt;&gt;$ErrLogErroCount=`diff $FileCountDbCurrOri $FileCountDbOri|wc -l`if [ $RETVAL -ne 0 -o $ErroCount -ne 0] then mail -s "`uname -n $(date +%F) err`" 31333741-@qq.com &lt;$ErrLogfi 然后可以加入定时任务 面试题15：开发Rsync服务启动脚本问题分析 要使用系统函数库技巧 要用函数 可被chkconfig管理 1234567891011121314151617181920212223242526272829303132333435363738394041424344#!/bin/bash# chkconfig: 2345 20 80# description: Rsyncd Startup scripts by oldboy.if [ $# -ne 1 ] then echo $"usage:$0 &#123;start|stop|restart&#125;" exit 1fiif [ "$1" = "start" ] then rsync --daemon sleep 2 if [ `netstat -lntup|grep rsync|wc -l` -gt 1 ] then echo "rsyncd is started." exit 0 fielif [ "$1" = "stop" ] then killall rsync &amp;&gt;/dev/null sleep 2 if [ `netstat -lntup|grep rsync|wc -l` -eq 0 ] then echo "rsyncd is stopped" exit 0 fielif [ "$1" = "restart" ] then killall rsync sleep 2 killpro=`netstat -lntup|grep rsync|wc -l` rsync --daemon sleep 2 startpro=`netstat -lntup|grep rsync|wc -l` if [ $killpro -eq 0 -a $startpro -ge 1 ] then echo "rsyncd is restarted" exit 0 fielse echo $"usage:$0 &#123;start|stop|restart&#125;" exit 1fi 面试题16：开发MySQL多实例启动脚本123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657#!/bin/bash####################this scripts is created by oldboy at 2007-06-09#blog:http://oldboy.blog.51cto.com####################initPort=3306MysqlUser="root"MysqlPass="oldboy123"CmdPath="/appliction/mysql/bin"#startup functionstart()&#123; if [ `netstat -lnt|grep "$Port"|wc -l` -eq 0 ] then printf "Starting MySQL...\n" /bin/sh $&#123;CmdPath&#125;/mysqld_safe --defaults-file=/data/$&#123;Port&#125;/my.cnf 2&gt;&amp;1 &gt; /dev/null &amp; else printf "MySQL is running...\n" fi&#125;#stop functionstop()&#123; if [ `netstat -lnt|grep "$Port"|wc -l` -eq 0 ] then printf "Stoping MySQL...\n" $&#123;CmdPath&#125;/mysqladmin -u $&#123;MysqlUser&#125; -p$&#123;MysqlPass&#125; -S /data/$&#123;Port&#125;/mysql.sock shutdown else printf "MySQL is stopped...\n" fi&#125;#restart functionrestart()&#123; printf "Restarting MySQL...\n" stop sleep 2 start&#125;case "$1" instart) start ;;stop) stop ;;restart) restart ;;*) printf "Usage: $0 &#123;start|stop|restart&#125;\n"esac 面试题21：开发脚本管理服务端LVS在LVS负载均衡主节点上，开发管理LVS服务的脚本ip_vs 问题分析利用ipvsadm可以启动并配置好LVS服务12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273#!/bin/bash# Written by oldboy# QQ:31333741# description: Config Director vip and ipvs. /etc/init.d/functionsVIP=10.0.0.3INTERFACE=eth0SubINTERFACE=$&#123;INTERFACE&#125;:`echo $VIP|cut -d. -f4`PORT=80GW=10.0.0.254RETVER=0IP=/sbin/ipROUTE=/sbin/routeIPVSADM=/sbin/ipvsadmARPING=/sbin/arpingRIPS=( #&lt;==定义realserver节点IP数组 10.0.0.7 10.0.0.8 )function usage ()&#123; echo "Usgae : $0 &#123;start|stop|restart&#125;" return 1&#125;function ipvsStart()&#123; #&lt;==配置ipvs $IP addr add $VIP/24 dev $&#123;INTERFACE&#125; label $SubINTERFACE #&lt;==添加VIP。 $ROUTE add -host $VIP $SubINTERFACE #&lt;==添加VIP对应主机路由 $IPVSADM -C $IPVSADM -A -t $VIP:$PORT -s wrr -p 60 #&lt;==生成ipvs实例 for ((i=0; i&lt;`echo $&#123;\#RIPS[*]&#125;`;i++)) do $IPVSADM -a -t $VIP:$PORT -r $&#123;RIPS[$i]&#125;:$PORT -g -w 1 #&lt;==添加节点 done RETVAR=$? # update MAC $ARPING -c 1 -I $&#123;INTERFACE&#125; -s $VIP $GW &amp;&gt;/dev/null if [ $RETVAR -eq 0 ] then action "Ipvsadm started." /bin/true else action "Ipvsadm stopped." /bin/false fi return $RETVAR &#125;main ()&#123; #judge argv num if [ $\# -ne 1 ]; then usage $0 fi case "$1" in start) ipvsStart ;; stop) ipvsStop ;; restart) ipvsStop ipvsStart ;; *) usage $0 ;; esac&#125;#start operatingmain $* 面试题 22：LVS节点健康检查及管理脚本模拟keepalived健康检查功能管理LVS节点，当节点挂掉时从服务器池中将其剔除，好了后再将其加入到服务器池中来. 问题分析123456789101112131415161718192021222324252627#!/bin/bash#created by oldboy 201308IPVSADM=/sbin/ipvsadmVIP=10.0.0.3PORT=80RIPS=(10.0.0.710.0.0.8)while truedo for((i=0;i&lt;$&#123;\#RIPS[*]&#125;;i++)) do PORT_COUNT=`nmap $&#123;RIPS[$i]&#125; -p $PORT|grep open|wc -l` if [ $PORT_COUNT -ne 1 ];then if [ `$IPVSADM -Ln|grep $&#123;RIPS[$i]&#125;|wc -l` -ne 0 ];then $IPVSADM -d -t $VIP:$PORT -r $&#123;RIPS[$i]&#125;:$PORT &gt;/dev/null 2&gt;&amp;1 fi else if [ `$IPVSADM -Ln|grep $&#123;RIPS[$i]&#125;|wc -l` -eq 0 ];then $IPVSADM -a -t $VIP:$PORT -r $&#123;RIPS[$I]&#125;:$PORT &gt;/dev/null 2&gt;&amp;1 fi fi done sleep 5done 面试题 23: LVS客户端配置脚本12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849#!/bin/bash# Written by oldboy# description: Config realserver lo and apply noarpRETVAR=0VIP=( 10.0.0.3 10.0.0.4). /etc/init.d/functionscase "$1" in start) for ((i=0;i&lt;`echo $&#123;\#VIP[*]&#125;`;i++)) do interface="lo:`echo $&#123;VIP[$i]&#125;|awk -F . '&#123;print $4&#125;'`" /sbin/ip addr add $&#123;VIP[$i]&#125;/24 dev lo label $interface REVTAR=$? done echo "1" &gt;/proc/sys/net/ipv4/conf/lo/arp_ignore echo "2" &gt;/proc/sys/net/ipv4/conf/lo/arp_announce echo "1" &gt;/proc/sys/net/ipv4/conf/all/arp_ignore echo "2" &gt;/proc/sys/net/ipv4/conf/all/arp_announce if [ $RETVAR -eq 0 ];then action "Start LVS Config of RearServer." /bin/true else action "Start LVS Config of RearServer." /bin/false fi ;; stop) for ((i=0;i&lt;`echo $&#123;\#VIP[*]&#125;`;i++)) do interface="lo:`echo $&#123;VIP[$i]&#125;|awk -F . '&#123;print $4&#125;'`" /sbin/ip addr del $&#123;VIP[$i]&#125;/24 dev lo label $interface &gt; /dev/null 2&gt;&amp;1 done echo "0" &gt;/proc/sys/net/ipv4/conf/lo/arp_ignore echo "0" &gt;/proc/sys/net/ipv4/conf/lo/arp_announce echo "0" &gt;/proc/sys/net/ipv4/conf/all/arp_ignore echo "0" &gt;/proc/sys/net/ipv4/conf/all/arp_announce if [ $RETVAR -eq 0 ];then action "Close LVS Config of RearServer." /bin/true else action "Close LVS Config of RearServer." /bin/false fi ;; *) echo "Usage: $0 &#123;start|stop&#125;" exit 1esacexit $RETVAR 面试题24 : 模拟Keepalived软件高可用在LVS服务端备用节点上,模拟keepalived vrrp功能,监听主节点,如果主节点不可访问,则启动备节点并配置LVS服务,接管主节点的资源并对用户提供服务(注意ARP缓存) 问题分析 监测主节点是否宕机,可以使用ping或nmap命令 如果主节点宕机,则调用管理LVS的服务脚本,执行LVS配置123456789101112131415161718192021#!/bin/bash# Author:oldboy training# Blog:http://oldboy.blog.51cto.comVIP=10.0.0.3PORT=80ipvs_tools=`rpm -qa ipvsadm|wc -l`if [ $ipvs_tools -ne 1 ] then yum install ipvsadm -yfiwhile truedo ping -w2 -c2 $&#123;VIP&#125; &gt;/dev/null 2&gt;&amp;1 if [ $? -ne 0 ];then /bin/sh ./19_21_1.sh start &gt;/dev/null 2&gt;&amp;1 else /bin/sh ./19_21_1.sh stop &gt;/dev/null 2&gt;&amp;1 fi sleep 5done 面试题 26:编写等腰三角形图形字符1234567891011121314#!/bin/bashread -p "Please Enter a number:" Linefor ((i=1;i&lt;=Line;i++))do for ((j=$Line-$i;j&gt;0;j--)); do echo -n ' ' done for ((h=1;h&lt;=$((2*$i-1));h++)) do echo -n '*' done echodone 面试题29 Nginx 负载节点状态监测12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364#!/bin/bashRIPS=( 10.0.0.7 10.0.0.8)file_location=/var/html/test.html[ -e "$file_location" ]|| mkdir `dirname $file_location` -pfunction web_result &#123; rs=`curl -I -s $1|awk 'NR==1&#123;print $2&#125;'` return $rs&#125;function new_row &#123; cat &gt;&gt; $file_location &lt;&lt;eof &lt;tr&gt; &lt;td bgcolor="$4"&gt;$1&lt;/td&gt; &lt;td bgcolor="$4"&gt;$2&lt;/td&gt; &lt;td bgcolor="$4"&gt;$3&lt;/td&gt; &lt;/tr&gt;eof&#125;function auto_html &#123; web_result $2 rs=$? if [ $rs -eq 200 ] then new_row $1 $2 up green else new_row $1 $2 down red fi &#125;function main()&#123; while true do cat &gt;&gt; $file_location &lt;&lt;eof &lt;h4&gt;Oldboy Nginx Service Status Of RS :&lt;/h4&gt; &lt;meta http-equiv="refresh" content="1"&gt; &lt;table border="1"&gt; &lt;tr&gt; &lt;th&gt;NO:&lt;/th&gt; &lt;th&gt;IP:&lt;/th&gt; &lt;th&gt;Status:&lt;/th&gt; &lt;/tr&gt;eof for ((i=0;i&lt;$&#123;\#RIPS[*]&#125;;i++));do auto_html $i $&#123;RIPS[$i]&#125; done cat &gt;&gt; $file_location &lt;&lt;eof &lt;/table&gt;eof sleep 2 &gt; $file_location done&#125;main $*]]></content>
    </entry>

    
    <entry>
      <title><![CDATA[第八 面试题实战 一]]></title>
      <url>%2F2017%2F03%2F29%2FOldboy_Shell%2F8day_1%2F</url>
      <content type="text"><![CDATA[第八 面试题实战 一@(shell脚本)[学习] [toc] 前言本章内容来自《跟老男孩学Linux运维：Shell编程实战》第19章内容。可以说本篇内容相当于整本书的一个总结实战 面试题1：批量生成随机字符文件名使用for循环在/oldboy目录下批量创建10个html文件，其中每个文件需要包含10个随机小写字母加固定字符串oldboy。例如：txynzwofgg_oldboy.html 分析随机生成小写字母，可以使用openssl函数生成123456789101112#!/bin/bash#19.1.1随机生成字符#author:oldboy#blog:http://oldboy.blog.51cto.comPath=/oldboyNum=10[ -d "$Path" ] || mkdir -p $Pathfor n in `seq $Num`do random=$(openssl rand -base64 40|sed 's#[^a-z]##g'|cut -c 2-11) touch $Path/$&#123;random&#125;_oldboy.htmldone 面试题2：批量改名将19.1.1所得文件中的oldboy改成oldgirl并且将扩展名html全部大写 问题分析可以使用sed加也可以使用for循环。1234for i in `ls`do mv -f $i `echo $i|sed &apos;s/oldboy\.html/oldgirl.\Uhtml/g&apos;`done 也可以使用专门的改名命令，rename1rename oldboy.html oldgirl.HTML *.html 面试题3：批量创建特殊要求用户批量创建10个系统账号oldboy01-oldboy10并设置密码(密码为随机数，要求是字符和数字的混合) 问题分析主要使用useradd命令和passwd --stdin命令一个创建用户，一个传入密码,随机密码可以用openssl来创建12345678910111213141516#!/bin/bash#author:oldboy#blog:http://oldboy.blog.51cto.comUser="oldboy"Passfile="/tmp/user.log"for Num in `seq -w 10`do useradd $User$Num #&lt;==创建用户 Pass=$(openssl rand -base64 40|sed 's#[^a-z0-9]##g'|cut -c 2-11) echo "$Pass"|passwd --stdin $User$Num #&lt;==设置密码 echo -e "user:$User$Num\tpasswd:$Pass" &gt;&gt; $Passfiledoneecho "----------this is oldboy trainning class contents---------"echo "Passfile:$Passfile"cat $Passfile 面试题4：扫描网络内存活主机判断某个网段内当前在线的ip有哪些？ 问题分析有个实用的命令nmap一般预装，没有的话yum install nmap -y没有yum的话，nmap官网。12345#!/bin/bashCmd="nmap -sP " #&lt;==快速ping测Ip="10.0.0.0/24"Cmd2="nmap-sS " #&lt;==检测端口$CMD $Ip|awk '/Nmap scan report for/ &#123;print $NF&#125;' 面试题5：解决DDOS攻击问题分析根据Web日志或网络连接数，监控当某个ip并发连接数或短时内PV达到100时，即调用防火墙命令封掉对应IP。防火墙命令：iptables -I INPUT -s IP -j DROP12345678910111213141516171819202122232425262728293031323334353637383940414243#!/bin/bash# 10_10_3.shfile=$1JudgeExt()&#123; \#&lt;==定义判断扩展名的函数，可以传入日志文件 if expr "$1" : ".*\.log" &amp;&gt;/dev/null then : #&lt;==冒号表示什么都不做 else echo $"usage:$0 xxx.log" exit 1 fi&#125;IpCount()&#123; \#&lt;==分析日志，对访问的IP去重排序。 grep "ESTABLISHED" $1|awk -F "[ :]+" '&#123; ++S[$(NF-3)]&#125; END &#123;for(key in S) print S[key],key&#125;'|sort -rn -k1|head -5 &gt;tmp/tmp.log&#125;ipt()&#123; local ip=$1 if [ `iptables -L -n|grep "$ip"|wc -l` -lt 1 ] then iptables -I INPUT -s $ip -j DROP echo "$line is dropped" &gt;&gt; /tmp/droplist_$(date +%F).log fi&#125;main()&#123; JudgeExt $file while true do IpCount $file while read line do ip=`echo $line|awk '&#123;print $2&#125;'` count=`echo $line|awk '&#123;print $1&#125;'` if [ $count -gt 3 ] then ipt $ip fi done&lt;/tmp/tmp.log sleap 180 done&#125;main 面试题6：MySQL数据库分库备份问题分析使用for循环12345678910111213#!/bin/bashPATH="/application/mysql/bin:$PATH" #&lt;==定义mysql命令所在路径DBPATH=/server/backupMYUSER=rootMYPASS=oldboy123SOCKET=/data/3306/mysql.sockMYCMD="mysql -u$MYUSER -p$MYPASS -S $SOCKET"MYDUMP="mysqldump -u$MYUSER -p$MYPASS -S $SOCKET"[ ! -d $DBPATH ] &amp;&amp; mkdir -p $DBPATHfor dbname in `$MYCMD -e "show databases;"|sed '1,2d'|egrep -v "mysql|schema"`do $MYDUMP $dbname|gzip &gt;$DBPATH/$&#123;dbname&#125;_$(date +%F).sql.gzdone 面试题7：MYSQL分库分表备份问题分析和上面一样，只是多一个循环嵌套1234567891011121314151617#!/bin/bashPATH="/application/mysql/bin:$PATH" #&lt;==定义mysql命令所在路径DBPATH=/server/backupMYUSER=rootMYPASS=oldboy123SOCKET=/data/3306/mysql.sockMYCMD="mysql -u$MYUSER -p$MYPASS -S $SOCKET"MYDUMP="mysqldump -u$MYUSER -p$MYPASS -S $SOCKET"[ ! -d $DBPATH ] &amp;&amp; mkdir -p $DBPATHfor dbname in `$MYCMD -e "show databases;"|sed '1,2d'|egrep -v "mysql|schema"`do mkdir $DBPATH/$&#123;dbname&#125;_$(date +%F) -p #&lt;==创建对应目录 for table in `$MYCMD -e "show tables for $dbname;"|sed '1d'` do $MYDUMP $dbname $table|gzip &gt;$DBPATH/$&#123;dbname&#125;_$(date +%F)/$&#123;dbname&#125;_$&#123;table&#125;.sql.gz donedone 面试题8：利用bash for循环打印下面字母数不大于6的单词问题分析可以使用${\#char}命令来获取单词长度 面试题9：MySQL主从复制异常监控问题分析开发一个守护进程脚本，每30s监控一次MySQL主从复制异常12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788#!/bin/bash###################### this script function is :# check_mysql_slave_replication_status# USER YYYY-MM-DD - ACTION# oldboy 2009-02-10 - Created#####################path=/server/scripts #&lt;== 定义脚本存放路径MAIL_GROUP="1111@qq.com 2222@qq.com"PAGER_GROUP="18600338340 18911718229"LOG_FILE="/tmp/web_check.log"USER=rootPASSWORD=oldboy123PORT=3307MYSQLCMD="mysql-u$USER -p$PASSWORD -S /data/$PORT/mysql.sock" #&lt;==登陆数据库命令error=(1008 1007 1062) #&lt;==可忽略的主从复制错误号RETVAL=0[ ! -d "$path" ] &amp;&amp; mkdir -p $pathfunction JudgeError()&#123; \#&lt;==定义判断主从复制错误的函数 for((i=0;i&lt;$&#123;\#error[*]&#125;;i++)) do if [ "$1" == "$&#123;error[$i]&#125;" ] #&lt;==如果传入的错误号和数组里的元素相匹配，则执行then后面的命令 then echo "MYSQL slave errorno is $1,auto repairing it." $MYSQLCMD -e "stop slave;set global sql_slave_skip_counter=1;start slave;" #&lt;==自动修复 fi done return $1&#125;function CheckDb()&#123; \#&lt;==定义检查数据库主从复制状态的函数 status=($(awk -F ':' '/_Running|Last_Errno|_Behind/&#123;print $NF&#125;' slave.log)) expr $&#123;status[3]&#125; + 1 &amp;&gt;/dev/null #&lt;==这个是延迟状态，用于进行是否为数字的判断 if [ $? -ne 0 ];then status[3]=300 #&lt;==赋值300，当数据库出现复制故障时，延迟这个状态值有可能是NULL，即非数字 fi if [ "$&#123;status[0]&#125;" == "Yes" -a "$&#123;status[1]&#125;" == "Yes" -a $&#123;status[3]&#125; -lt 120 ] #&lt;==两个线程都为Yes，并且延迟小于120s，即认为复制状态是正常的。 then #echo "Mysql slave status is ok" return 0 else #echo "mysql replcation is failed" JudgeError $&#123;status[2]&#125; #&lt;==否则，将错误号$&#123;status[2]&#125;传入JudgeError函数 fi&#125;function MAIL()&#123; #&lt;==定义邮件函数 local SUBJECT_CONTENT=$1 #&lt;==将函数的第一个传参赋值给主题变量。 for MAIL_USER in `echo $MAIL_GROUP` do mail -s "$SUBJECT_CONTENT " $MAIL_USER &lt;$LOG_FILE done&#125;function PAGER()&#123; #&lt;==定义手机函数 for PAGER_USER in `echo $PAGER_GROUP` do TITLE=$1 CONTACT=$PAGER_USER HTTPGW=http:/../ #&lt;==发送短信地址 ##发送短信报警的命令 #send_message method1 curl -d cdkey=XXXX -d password=xxxx -d phone=$CONTACT -d message="$TITLE[$2]" $HTTPGW done&#125;function SendMsg()&#123; if [ $1 -ne 0 ] then RETVAL=1 NOW_TIME=`date +"%Y-%m-%d %H:%M:%S"` SUBJECT_CONTENT="mysql slave is error,errorno is $2,$&#123;NOW_TIME&#125;." echo -e "$SUBJECT_CONTENT"|tee $LOG_FILE MAIL $SUBJECT_CONTENT PAGER $SUBJECT_CONTENT $NOW_TIME else echo "Mysql slave status is ok" RETVAL=0 fi return $RETVAL&#125;function main()&#123; while true do CheckDb SendMsg $? sleep 30 done&#125;main 面试题10：比较整数大小问题分析先判断是否传参，再判断参数个数，再判断参数类型，最后比较 面试题11：菜单自动化软件部署问题分析同上]]></content>
    </entry>

    
    <entry>
      <title><![CDATA[第七 Expect自动化交互式程序]]></title>
      <url>%2F2017%2F03%2F22%2FOldboy_Shell%2F7day%2F</url>
      <content type="text"><![CDATA[第七 Expect自动化交互式程序@(shell脚本)[学习] [toc] 什么是ExpectExpect式一个用来实现自动交互功能的软件套件，是基于TCL的脚本编程工具语言，方便学习，功能强大 Expect程序自动交互的重要命令spawn命令语法：123spawn [ 选项 ] [ 需要自动交互的命令或程序 ]########spawn ssh root@192.168.33.130 uptime expect命令语法：12345expect 表达式 [ 动作 ]############spawn ssh root@192.168.33.130 uptimeexpect "*password" &#123; send "123456\r" &#125;# &#123;&#125;内空格不敏感，两端留空格与不留空格一样 expect命令实践：12345#!/usr/bin/expect #&lt;==脚本解释器spawn ssh root@192.168.33.130 uptimeexpect "*password" send "123456\r"expect eof #&lt;==想要输出结果，还必须加eof，表示expect结束 说明： exp_send和send类似 expect{}类似多行expect. 匹配多个字符串，需要在每次匹配并执行动作后，加上exp_continue。 test.sh123456789101112131415#!/bin/bash#Author:summingyu#Blog:https://summingyu.github.io/#Time:2017-02-23 15:48:09#Name:test.sh#Version:V1.0#Description: This is a test script.echo "hello,world"read -p 'Please input your username:' nameread -p 'Please input your password:' passread -p 'Please input your username:' nameread -p 'Please input your mail:' mailecho -n "your name is $&#123;name&#125;."echo -n "your password is $&#123;pass&#125;"echo -n "your mail is $&#123;mail&#125;" test.exp12345678#!/usr/bin/expectspawn /bin/sh test.shexpect &#123; "username" &#123; exp_send "123456\r";exp_continue &#125; "pass" &#123; send "333\n" ;exp_continue&#125; "mail" &#123; send "333\n"&#125;&#125;#expect eof #&lt;==匹配全有exp_continue时加这个会报错 执行expect test.exp结果如下1234567spawn /bin/sh test.shhello,worldPlease input your username:123456Please input your password:333Please input your username:123456Please input your mail:333your name is 123456.your password is 333your mail is 333 如果需要一次匹配多个字符串，那么不同的匹配之间就要加上exp_continue，否则expect将不会自动输入指定的字符串。最后一个的结尾就不需要加上exp_continue了。 且每次匹配都是会重新匹配，顺序可以不同 例如将匹配脚本test.sh的mail行插入到上面123456read -p 'Please input your username:' nameread -p 'Please input your password:' pass#在这里插入一行mailread -p 'Please input your mail:' mailread -p 'Please input your username:' nameread -p 'Please input your mail:' mail 结果如下123456spawn /bin/sh test.shhello,worldPlease input your username:123456Please input your password:333Please input your mail:333Please input your username: #&lt;==在这里停顿！ send_user命令类似echo -e 打印脚本信息 常用命令总结 expect命令 作用 spawn 一开始使用的命令，通过spawn执行命令，然后所有的expect操作都在这个执行的命令或进程中进行交互 expect 获取交互信息，看是否与实践指定的信息相匹配，匹配则执行指定内容后的动作 send expect中的动作命令，发送指定字符串给系统。还有个类似命令exp_send。 exp_continue 属于一种动作命令，用于多次匹配的动作中，相当于循环的continue send_user 相当于echo exit 退出expect脚本 Expect程序变量普通变量定义变量语法：set 变量名 变量值 打印变量语法：puts $变量名send_user也可以用于打印输出 特殊参数变量在Expect中\$argv表示参数数组，可以是用[lindex \$argv n]接收Expect脚本传参。n从0开始。 但是[lindex \$argv 0]相当于shell里的\$1set file [lindex $argv 0]获取的是\$1 除了位置参数外，还有其他特殊参数$argc表示传参的个数，$argv0表示脚本名字 if条件语句123if &#123; 条件表达式 &#125; &#123; 指令&#125; 或12345if &#123; 条件表达式 &#125; &#123; 指令&#125; else &#123; 指令&#125; 说明：if关键字后面有空格，else关键字前后都有空格，{ 条件表达式 }里面可以没有空格，但外面与指令的大括号相连的地方要有空格 Expect中的关键字eof关键字end-of-file。用于匹配结束符。例如文件的结束符，FTP传输停止等情况，在这个关键字后跟上动作来做进一步控制，特别是ftp交互操作方面，它的作用很大。 timeout关键字timeout是expect中一个控制时间的关键字，全局性的。脚本执行到达规定时间后，会直接执行结尾的timeout动作。0表示立即超时，-1表示永不超时在expect{}中还可以使用这个语法12345expect &#123; -timeout 3 "yes/no" &#123; exp_send "yes\r";exp_continue &#125; timeout &#123; puts "Request timeout by oldboy.";return &#125;&#125;]]></content>
    </entry>

    
    <entry>
      <title><![CDATA[第六 shell脚本开发规范及trap]]></title>
      <url>%2F2017%2F03%2F15%2FOldboy_Shell%2F6day%2F</url>
      <content type="text"><![CDATA[第六 shell脚本开发规范及trap@(shell脚本)[学习] [toc] 基本规范对于需要环境变量的java程序脚本等，在写脚本前，最好通过export重新声明环境变量，以免在定时任务等场合的使用中出现问题。 shell脚本的调试shell的语法调试并不是很智能，报错也不是很精准，因此就需要我们在开发规范和书写脚本上多下功夫。 shell脚本调试技巧 使用dos2unix命令处理windows下的开发脚本 使用bash命令参数调试，-n不会执行该脚本，仅查询脚本语法是否有问题。 cat -n script.sh 输出行号shell开发环境的配置和优化利用别名，将vi命令替换为vimecho &#39;alias vi=vim&#39; &gt;&gt; /etc/profile Linux信号及trap命令信号列表 信号 说明 HUP(1) 挂起，通常因终端掉线或用户退出而引发 INT(2) 中断，通常因按下Ctrl+c组合键引发 QUIT(3) 退出，通常因按下Ctrl+\组合键而引发 ABRT(6) 中止，通常因某些严重的执行错误而引发 ALRM(14) 报警，通常用来处理超时 TERM(15) 终止，通常在系统关机时发送 TSTP(20) 停止进程的运行，但该信号可以被处理和忽略，通常因按下Ctrl+z组合键而引发 使用trap控制信号trap command signalsignal指接收到的信号，command指接收到该信号应采取的行动使用trap &#39;&#39; siganl屏蔽信号,trap &#39;:&#39; siganl 取消屏蔽]]></content>
    </entry>

    
    <entry>
      <title><![CDATA[vimrc配置]]></title>
      <url>%2F2017%2F02%2F20%2FOldboy_Shell%2Fvimrc%2F</url>
      <content type="text"><![CDATA[vimrc配置@(shell脚本)[学习] [toc] 《跟老男孩学习linux运维——shell》的第16章内容,路径为~/.vimrc。没有则自己创建.一下内容纯手打，巩固记忆 内容123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206" ~/.vimrc" vim config file" date 2008-09-05" Created by oldboy" blog:http://oldboy.blog.51cto.com"""""""""""""""""""""""""""" =&gt; 全局变量"""""""""""""""""""""""""""" 关闭兼容模式set nocompatible" 设置历史记录步数set history=100" 开启相关插件filetype onfiletype plugin onfiletype indent on" 当文件在外部被修改时，自动更新该文件set autoread" 激活鼠标的使用"set mouse=a"""""""""""""""""""""""""""" =&gt; 字体和颜色""""""""""""""""""""""""""" " 开启语法syntax enable" 设置字体"set guifont=dejaVu\ Sans\ MONO\ 10""" 设置配色"colorscheme desert " 高亮显示当前行set cursorlinehi cursorline guibg=#00ff00hi CursorColumn guibg=#00ff00""""""""""""""""""""""""""" " =&gt; 代码折叠功能 by oldboy"""""""""""""""""""""""""""" 激活折叠功能set foldenable" 设置按照语法方式折叠(可简写set fdm=XX)" 有6种折叠方法：" manual 手工定义折叠" indent 更多的缩进表示更高级别的折叠" expr 用表达式来定义折叠" syntax 用语法高亮来定义折叠" diff 对没有更改的文本进行折叠" marker 对文中的标志进行折叠set foldmethod=manual" 设置折叠区域的宽度" 如果不为0，则在屏幕左侧显示一个折叠标识列" 分别用"-"和"+"来表示打开和关闭的折叠。set foldcolumn=0" 设置折叠层数为3setlocal foldlevel=3" 设置为自动关闭折叠set foldclose=all" 用空格键来代替zo和zc快捷键实现开关折叠" zo O-pen a fold (打开折叠)" zc C-lose a fold (关闭折叠)" zf F-old creation (创建折叠)nnoremap &lt;space&gt; @=((foldclosed(line('.')) &lt; 0 ) ? 'zc' : 'zo' )&lt;CR&gt;"""""""""""""""""""""""""""" =&gt; 文字处理 by oldboy"""""""""""""""""""""""""""" 使用空格来代替Tabset expandtab" 设置所有的Tab和缩进为4个空格set tabstop=4" 设定 &lt;&lt; 和 &gt;&gt; 命令移动时的宽度为 4set shiftwidth=4" 使得按退格键时可以一次删掉4个空格set softtabstop=4set smarttab" 缩进，自动缩进( 继承前一行的缩进 )"set autoindent 命令关闭自动缩进，时下面配置的缩写。" 可使用autoindent命令的简写，即 “:set ai” 和 “:set noai”" 还可以使用“:set ai sw=4”在一个命令中打开缩进并设置缩进级别。set ai" 智能缩进set si" 自动换行set wrap" 设置软宽度set sw=4"""""""""""""""""""""""""""" =&gt; Vim 界面by oldboy"""""""""""""""""""""""""""" Turn on WiLd menuset wildmenu" 显示标尺set ruler" 设置命令行的高度set cmdheight=1" 显示行数set nu"Do not redraw, when running macros.. lazyredrowset lz" 设置退格set backspace=eol,start,indent" Bbackspace and cursor keys wrap toset whichwrap+=&lt;,&gt;,h,l"Set magic on(设置魔术)set magic" 关闭遇到错误时的声音提示" 关闭错误信息响铃set noerrorbells" 关闭使用可视响铃代替呼叫set novisualbell" 显示匹配的括号( [ &#123; 和 &#125; ] )set showmatch"How many tenths of a second to blinkset mat=2" 搜索时高亮显示搜索到的内容set hlsearch" 搜索时不区分大小写" 还可以使用简写( “:set ic” 和 “:set noic” )set ignorecase"""""""""""""""""""""""""""" =&gt; 编码设置"""""""""""""""""""""""""""" 设置编码set encoding=utf-8" 设置文件编码set fileencodings=ucs-bom,utf-8,cp936set fileencoding=utf-8" 设置终端编码set termencoding=utf-8"""""""""""""""""""""""""""" =&gt; 其他设置 by oldboy 2010"""""""""""""""""""""""""""" 开启新行时使用智能缩进set smartindentset cinset showmatch" 隐藏工具栏set guioptions-=T" 隐藏菜单栏set guioptions-=m" 置空错误码铃声的终端代码set vb t_vb=" 显示状态栏( 默认值为 1，表示无法显示状态栏 )set laststatus=2" 粘贴不换行问题的解决set pastetoggle=&lt;F9&gt;" 设置背景色set background=dark" 设置高亮相关highlight Search ctermbg=black ctermfg=white guifg=white guibg=black" shell脚本开头自动增加解释器及作者等版权信息autocmd BufNewFile *.py,*.cc,*.sh,*.go,*.java exec ":call SetTitle()"func SetTitle() if expand("%:e") == 'sh' call setline(1, "#!/bin/bash") call setline(2, "#Author:summingyu") call setline(3, "#Blog:https://summingyu.github.io/") call setline(4, "#Time:".strftime("%F %T")) call setline(5, "#Name:".expand("%")) call setline(6, "#Version:V1.0") call setline(7, "#Description: ") endifendfunc]]></content>
    </entry>

    
    <entry>
      <title><![CDATA[第五 shell函数]]></title>
      <url>%2F2017%2F02%2F15%2FOldboy_Shell%2F5day%2F</url>
      <content type="text"><![CDATA[第五 shell函数@(shell脚本)[学习] [toc] 函数的执行执行不带参数的函数时，直接输入函数名即可 执行Shell函数时，函数名前的function和函数后面的小括号都不要带 函数的定义必须在执行的程序前面定义或加载 Shell执行系统中各种程序的执行顺序为：系统别名-&gt;函数-&gt;系统命令-&gt;可执行文件 函数执行时，会和调用它的脚本共用变量，也可以为函数设定局部变量及特殊位置参数。 在shell函数里面，return命令的功能与exit类似，return的作用是退出函数，而exit是退出脚本文件 return语句会返回一个返回值给调用函数的当前程序，而exit会返回一个返回值给执行程序的当前shell 如果将函数存放在独立的文件中，被脚本加载使用时，需要使用source或者”.“来加载 在函数内一般使用local定义局部变量 带参数的函数执行方法如下： 函数名 args1 args2 .. shell的位置参数都可以作为函数的参数来使用。 此时父脚本的参数临时地被函数参数所掩盖或隐藏 $0比较特殊，它仍然时父脚本的名称 当函数执行完成时，原来的命令行脚本的参数即可恢复 函数的参数变量时在函数体里面定义的 学习了函数后，应该尽量将脚本功能模块化，每个模块实现一个功能，并且让脚本可以通用。 case条件语句case条件语句相当于多分支的if/elif/else条件语句，但是它比这些条件语句看起来更规范更工整。12345678910case "ARGS" in value 1) command ;; value 2) pass ;; *) command3 ...esac case语句和if语句的实用性case语句比较适合变量值较少且为固定的数字或字符串集合的情况 case语句和if语句的常用场景 case主要写服务的启动脚本，传参不同且具有少量的字符串 几乎所有的case语句都可以用if语句来实现 case语句的特点及优势规范，易读while循环和until循环while循环使用与频率小于1分钟的循环处理，其他的while循环几乎都可以被for循环和crond功能代替123456789while &lt;条件表达式&gt;do command...done---------------------until &lt;条件表达式&gt;do command...done for和select循环语句for循环语句for循环主要用于执行次数有限的循环，而不是用于守护进程及无限循环1234for 变量名 in 变量取值列表do command...done 在此结构中“in 变量取值列表”可以省略，省略时相当于in “$@”，也就是for i in &quot;$@&quot; c语言型for循环1234for((exp1;exp2;exp3))do command...done 使用ls与awk实现批量改名1ls|awk -F "." '&#123;print "mv",$0,$1"_finished."$2&#125;'|bash 使用rename改名1rename "_finished" "" *.jpg select 循环语句select 循环语句的主要作用可能就是创建菜单，在执行带select循环语句脚本时，输出会按照数字顺序的列表显示一个菜单项，并显示提示符，同时等待用户输入数字顺序的列表进行选择。相当于半自动可控for循环。1234select 变量名 [ in 菜单取值列表 ]do command ...done 使用PS3=&#39;...&#39;来改变默认提示符$REPLY变量为上一个输入的值 循环控制及状态返回值break，continue，exit，return 命令 说明 break n 跳出整个循环，n表示跳出循环的层数 continue n 跳过本次循环，n表示跳过循环的次数 exit n 退出当前shell程序，n为状态返回值 return n 函数返回 以上n均可省略 shell数组1array=(value1 value2 ...) 输出数组的所有元素值123echo $&#123;array[*]&#125;#或echo $&#123;array[@]&#125; 动态定义数组123array=($(command))#或array=(`command`) 数组也是变量，所以前面的变量子串知识也试用与数组 。例如echo ${\#array[@]}获取数组长度]]></content>
    </entry>

    
    <entry>
      <title><![CDATA[第四 shell脚本的条件测试与比较&&if条件语句]]></title>
      <url>%2F2017%2F02%2F15%2FOldboy_Shell%2F4day%2F</url>
      <content type="text"><![CDATA[第四 shell脚本的条件测试与比较&amp;&amp;if条件语句@(shell脚本)[学习] [toc] 测试命令test结论：test命令测试的功能很强大，但是和[ ]、[[ ]]的功能有所重合，因此，在实际工作中选择一种适合自己的语法就好了。 文件测试表达式 常用文件测试操作符 说明 -d 文件 directory，目录 -f 文件 file，普通文件 -e 文件 exist，-e不辨别是目录还是文件 -r 文件 read，可读文件 -s 文件 size，文件大小不为0的文件 -w 文件 write，可写文件 -x 文件 executable，可执行文件 -L 文件 link，链接文件 f1 -nt f2 newer than 文件f1比f2新，根据修改时间计算 f1 -ot f2 older than 文件f1比f2旧，根据修改时间计算 提示：测试文件的读写执行等属性，不光是根据文件属性rwx的标识来判断，还要看当前执行测试的用户是否真的可以按照对应的权限操作该文件。tips: 测试变量时要加””，否则结果可能不对。变量没赋值返回结果也为真 字符串测试表达式 常用字符串测试操作符 说明 -n “字符串” no zero，字符串长度不为0 -z “字符串” zero，字符串长度为0 “串1”=”串2” 若字符串1等于字符串2，则为真，可使用”==”代替”=” “串1”!=”串2” 若字符串1不等于字符串2，为真 对字符串的测试一定要将字符串加双引号之后再进行比较。 比较字符串两段一定要有空格 整数二元比较操作符 在[]以及test中使用的比较符 在(())和[[]]中使用的比较符号 说明 -eq ==或= equal，相等 -ne != not equal，不等 -gt &gt; greater then， 大于 -ge &gt;= greater equal， 大于等于 -lt &lt; less then,小于 -le &lt;= less equal，小于等于 “=”和”!=”可以在[]中使用，但”&gt;”、”&lt;”要用反斜线”\”转义 比较符号两端也要有空格 [[]]是扩展的test命令，其语法更丰富也更复杂，建议除非是特殊的正则匹配等，在[]无法使用的情况下才会考虑使用[[]] 逻辑操作符 在[]以及test中使用的比较符 在(())和[[]]中使用的比较符号 说明 -a &amp;&amp; and -o \ \ or ! ! not if条件语句基本可以用测试表达式加&amp;&amp;或||代替简单的if语句。主要是嵌套if语句和多分支语句。if在脚本中是非常重要的模块。]]></content>
    </entry>

    
    <entry>
      <title><![CDATA[第三 shell变量的数值计算学习笔记]]></title>
      <url>%2F2017%2F02%2F13%2FOldboy_Shell%2F3day%2F</url>
      <content type="text"><![CDATA[第三 shell变量的数值计算学习笔记@(shell脚本)[学习] [toc] shell中常见的算术运算命令 运算操作符与运算命令 意义 (()) 用于整数运算的常用运算符 let 用于整肃运算，类似于(()) expr 可用于整数运算，但还有很多其他的额外功能 bc Linux下的一个计算器程序(适合整数及小树运算) $[] 用于整数运算 awk declare 定义变量值与属性，-i参数可以用于定义整形变量，做运算 (())双小括号数值运算 该命令使用参数的数字及变量，必须为整数(型) 在(())中使用变量时可以去掉变量前的\$符号，如果要输出，则需要\$符号 (())里的所有字符之间没有空格、有一个或多个空格，都不会影响结果expr的企业级实战 判断一个变量值或字符串是否为整数(使用expr $i + 1 &amp;&gt;/dev/null，判断$?的值是否为0) 判断文件扩展名是否符合要求(expr &quot;$1&quot; : &quot;*.pub&quot; &amp;&gt;/dev/null ) 通过expr计算字符串长度(expr length &quot;$char&quot;)基于shell的read命令格式: read [参数] [变量名] -p prompt: 设置提示信息 -t timeout: 设置等待时间/s]]></content>
    </entry>

    
    <entry>
      <title><![CDATA[第二 shell变量学习笔记]]></title>
      <url>%2F2017%2F02%2F08%2FOldboy_Shell%2F2day%2F</url>
      <content type="text"><![CDATA[第二 shell变量学习笔记@(shell脚本)[学习] [toc] shell中特殊且重要的变量 shell中的特殊位置参数变量 位置变量 作用说明 \$0 获取当前执行的shell脚本的文件名，如果执行脚本包含了路径，那么就包括脚本路径 \$n 获取当前脚本的第n个参数值，如果n大于9，则用大括号括起来，例如\${ 10 } \$# 获取当前执行的shell脚本后面接的参数的总个数 \$* 获取当前shell脚本所有传参的参数 \$@ 获取当前shell脚本所有传参的参数 Note: \$与\$@不加引号作用相同.都加双引号则有区别.“\$“相当于”\$1 \$2 \$3”“\$@”相当于”\$1” “\$2” “\$3” shift命令为将位置参数左移一位 shell进程中特殊状态变量 位置变量 作用说明 \$? 获取执行上一个命令的执行状态返回值( 0为成功,非零为失败 )常用 \$$ 获取当前执行的shell脚本的进程号( PID ),这个不常用 \$! 获取上一个在后台工作的进程的PID \$_ 获取在此之前执行的命令或脚本的最后一个参数(相当于快捷键Esc+.) Shell变量子串知识及实践Shell变量子串介绍 ID 表达式 说明 1 \${ parameter } 返回变量的内容 2 \${ #parameter } 返回变量内容的长度 3 \${ parameter:offset } 从位置offset之后开始提取子串到结尾 4 \${ parameter:offset:length } 从位置offset之后开始提取长度为length子串 5 \${ parameter#word } 从开头开始删除最短匹配的word子串 6 \${ parameter##word } 从开头开始删除最长匹配的word子串 7 \${ parameter%word } 从结尾开始删除最短匹配的word子串 8 \${ parameter%%word } 从结尾开始删除最长匹配的word子串 9 \${ parameter/pattern/string } 使用string代替第一个匹配的pattern 10 \${ parameter//pattern/string } 使用string代替所有匹配的pattern Note: # ## % %% 都是从开头或结尾匹配，如果中间出现符合的，但开头或结尾不符合也是无法匹配到的。即，不会出现截取掉中间部分的情况 Shell特殊扩展变量 表达式 说明 ${parameter:-word} 如果parameter的变量值为空或未赋值，则会返回word字符串并代替变量的值.并不会改变parameter的值 ${parameter:=word} 如果parameter的变量值为空或未赋值,则设置这个变量为word.位置变量和特殊变量不适用.基本同上一个表达式,但该变量额外给parameter变量赋值了 ${parameter:?word} 如果parameter的变量值为空或未赋值,那么word字符串将被作为标准错误输出,否则输出变量的值 ${parameter:+word} 如果parameter的变量值为空或未赋值,则什么都不做,否则word字符串将代替变量的值]]></content>
    </entry>

    
    <entry>
      <title><![CDATA[第一 shell基础学习笔记]]></title>
      <url>%2F2017%2F02%2F07%2FOldboy_Shell%2F1day%2F</url>
      <content type="text"><![CDATA[第一 shell基础学习笔记前言本系列为阅读《跟老男孩学习Linux运维——shell编程实战》笔记 几大脚本语言对比 shell脚本对于常规业务应用更符合Linux的简单、易用、高效的三大基本原则 PHP优势在于小型网站系统的开发 Python优势在于开发较复杂的运维工具软件、Web界面的管理工具和Web业务开发bash与sh的区别sh为bash的软连接，更规范的写法为#!bin/bashbash破壳漏洞检测执行下面命令1env x='() &#123; :;&#125;; echo be careful' bash -c "echo this is a test" 如果返回下面结果12be carefulthis is a test 则需要尽快升级bash。 source或.命令 source或.命令的功能是加载并执行相关脚本文件中的命令及语句相当于PHP中的include的功能。 使用sh执行脚本，是启动一个子shell来执行，所以脚本中定义的变量在脚本执行结束，关掉子shell后不会保留；而source则相当于在当前shell中执行，所以脚本中定义的变量将会保留。awk中调用变量对三个引号的特殊性 AWK\ETT ETT=123 ETT=’oldgirl’ ETT=”tingting” ETT=`pwd` awk ‘BEGIN { print “\$ETT” }’ \$ETT \$ETT \$ETT \$ETT awk ‘BEGIN { print $ETT }’ awk ‘BEGIN { print ‘$ETT’ }’ 正确 语法报错 awk ‘BEGIN { print “‘$ETT’” }’ 正确 正确 正确 正确]]></content>
    </entry>

    
    <entry>
      <title><![CDATA[部署rsync远程备份]]></title>
      <url>%2F2017%2F01%2F17%2Flinux%2Frsync%2F</url>
      <content type="text"><![CDATA[写在前面年终了！要回去过年，担心各个设备出问题，要一个备份机器将其他设备上的程序同步做灾备。 实施过程其中52为备份客户端，51为服务端 打通2.52与2.51之间的ssh免密码登陆(root用户) 在备份服务器52上使用命令ssh-keygen -t rsa -P &#39;&#39; -f /root/.ssh/id_rsa一次生成 或者运行ssh-keygen -t rsa**然后敲击三次回车生成密钥对 如果在2.51服务端上的/root/.ssh/目录下没有authorized_keys文件，则生成：touch authorized_keys 修改权限chmod 600 authorized_keys 将客户端上生成的id_rsa.pub追加到服务端authorized_keys文件中 在服务端51上使用scp命令将远程服务器上的id_rsa.pub下载到本地服务器scp -p root@192.168.2.52:/root/.ssh/id_rsa.pub /root/.ssh/id_rsa.pub_192.168.2.52 追加到authorized_keys文件中 cat /root/.ssh/id_rsa.pub_192.168.2.52 &gt;&gt;authorized_keys 修改ssh的配置文件/etc/ssh/sshd_config将下列三行注释去掉 12345678#RSAAuthentication yes#PubkeyAuthentication yes#AuthorizedKeysFile .ssh/authorized_keys##################修改后#############################RSAAuthentication yesPubkeyAuthentication yesAuthorizedKeysFile .ssh/authorized_keys 重启sshd服务：service sshd restart 到此已经打通2.51和2.52之间的ssh 保险起见，将每个服务器上的id_rsa.pub_*文件删除rm -f /root/.ssh/id_rsa.pub_* 使用rsync同步两台服务器程序修改51上的/etc/rsyncd.conf文件，没有则创建。权限64412345678910111213141516171819202122232425262728293031323334353637383940414243444546474849# /etc/rsyncd: configuration file for rsync daemon mode# See rsyncd.conf man page for more options.# configuration example:# uid = nobody# gid = nobodyuid = rootgid = root# use chroot = yesuse chroot = no# max connections = 4max connections = 4# pid file = /var/run/rsyncd.pidpid file = /var/run/rsyncd.pidlock file = /var/run/rsyncd.locklog file = /var/log/rsyncd.log# exclude = lost+found/# transfer logging = yes# timeout = 900timeout = 600# ignore nonreadable = yes dont compress = *.gz *.tgz *.zip *.z *.Z *.rpm *.deb *.bz2[exp_1] path = /exp comment = bakup exp_1_zipingtai #此行为备注行，可随意更改 ignore errors = yes read only = yes list = no hosts allow = 192.168.2.52 #限定允许访问的ip hosts deny = 0.0.0.0/0 #拒绝所有其他ip使用rsync同步 exclude = log/* #过滤文件及目录为相对path的路径 auth users = root secrets file = /etc/backserver.pas[tomcat] path = /usr/tomcat comment = bakup tomcat ignore errors = yes read only = yes list = no hosts allow = 192.168.2.52 hosts deny = 0.0.0.0/0 exclude = log/* logs/* webapps/ROOT/* work/* auth users = root secrets file = /etc/backserver.pas# 要同步其他程序可自行按上行格式同步 生成认证密码文件/etc/backserver.pas执行下列命令1234# root密码为123456；可以与登陆密码不一致echo root:123456 &gt; /etc/backserver.pas # 修改文件权限，否则服务起不来chmod 400 /etc/backserver.pas 启动服务端12345rsync --daemon# 观察是否启动成功,下列三种命令皆可lsof -i :873 netstat -an|grep 873ps -ef|grep rsync 客户端配置 创建密码文件 123echo 123456 &gt; /root/backserver.pas #与服务端密码一致# 更改密码文件权限，否则报错chmod 600 /root/backserver.pas 创建对应文件夹mkdir -pv /bak/exp_1 执行下面命令 1rsync -vzrtopg --bwlimit=1000 --delete --progress root@192.168.2.51::exp_1 /bak/exp_1/ --password-file=/root/backserver.pas --bwlimit参数是限定同步速度为1000kB/s--delete参数是同步时发现客户端有而服务端没有的文件则删除 优化 可以将exclude参数写入服务端配置文件中,例如： 123456789101112exclude = bin/ history/ #多个目录使用空格隔开# 如果过滤文件较多，可以使用参数exclude from# 注意：########################### 过滤目录不是按绝对值目录匹配的# 例如有两个目录bin/和foo/bin/# 则该参数会将两个bin目录都过滤掉# 如果要过滤foo/bin/则需要用foo/bin/# exclude = foo/bin/###########################exclude from = /home/exclude.list#exclude.list每行为一个参数，参数为相对路径 编写autobakup.sh备份脚本 1234567891011121314151617181920#!/bin/bash#auther: summingbest@gmail.comMONTH=`date +"%Y%m"`DAY=`date +"%d"`HOUR=`date +"%H"`MIN=`date +"%M"`tarname=/bak/exp/exp_1_$&#123;MONTH&#125;$&#123;DAY&#125;$&#123;HOUR&#125;.tar.gz[ ! -d /bak/exp ] &amp;&amp; mkdir -p /bak/exp;[ ! -d /bak/exp/exp_1 ] &amp;&amp; mkdir -p /bak/exp/exp_1;[ ! -d /bak/exp/tomcat ] &amp;&amp; mkdir -p /bak/exp/tomcat;#删除7天前的备份文件find /bak/exp -name "exp_1_*.tar.gz" -mtime +7 -type f|xargs rm -frsync -vzrtopg --bwlimit=1000 --delete --progress root@192.168.2.51::exp_1 /bak/exp/exp_1/ --password-file=/root/backserver.pasrsync -vzrtopg --bwlimit=1000 --delete --progress root@192.168.2.51::tomcat /bak/exp/tomcat/ --password-file=/root/backserver.pastar -zcvf $&#123;tarname&#125; /bak/exp/exp_1/ /bak/exp/tomcat/ 可以在客户端 将脚本放入指定的/bak/bin目录，并使用命令加入crontab，定时执行 1echo &apos;20 9 * * * /bin/sh /bak/bin/autobakup.sh&apos; &gt;&gt; /var/spool/cron/root 在其他服务器上配置只需要更改一些对应的参数即可 参考文献 ssh/scp免密码登陆 rsync简单配置 rsync百度文库详细参数 rsync常见错误]]></content>
    </entry>

    
    <entry>
      <title><![CDATA[vi指令說明(完整版)]]></title>
      <url>%2F2016%2F12%2F08%2Flinux%2Fvi%2F</url>
      <content type="text"><![CDATA[vi指令說明(完整版)本文学习自http://www2.nsysu.edu.tw/csmlab/unix/vi_command.htm vi 的操作模式vi 提供兩種操作模式：輸入模式(insert mode)和指令模式(command mode) 。當使用者進入 vi 後，即處在指令模式下，此刻鍵入之任何字元皆被視為 指令。在此模式下可進行刪除、修改等動作。若要輸入資料，則需進入輸入 模式。 輸入模式如何進入輸入模式 a (append) 由游標之後加入資料。 A 由該行之末加入資料。 i (insert) 由游標之前加入資料。 I 由該行之首加入資料。 o (open) 新增一行於該行之下供輸入資料之用。 O 新增一行於該行之上供輸入資料之用。 如何離開輸入模式 &lt;ESC&gt; 結束輸入模式。 指令模式游標之移動 h 向左移一個字元。 j 向上移一個字元。 k 向下移一個字元。 l 向右移一個字元。 0 移至該行之首 $ 移至該行之末。 ^ 移至該行的第一個字元處。 H 移至視窗的第一列。 M 移至視窗的中間那列。 L 移至視窗的最後一列。 G 移至該檔案的最後一列。 + 移至下一列的第一個字元處。 - 移至上一列的第一個字元處。 ( 移至該句之首。 (註一) ) 移至該句之末。 { 移至該段落之首。 (註二) } 移至該段落之末。 nG 移至該檔案的第 n 列。 n+ 移至游標所在位置之後的第 n 列。 n- 移至游標所在位置之前的第 n 列。 &lt;Ctrl&gt;&lt;g&gt; 會顯示該行之行號、檔案名稱、檔案中最末行之行號、游標 所在行號佔總行號之百分比。 註一：句子(sentence)在vi中是指以『！』、『.』或『？』結束的一串字。 註二：段落(paragraph)在vi中是指以空白行隔開的文字。 視窗的移動&lt;Ctrl&gt;&lt;f&gt; 視窗往下捲一頁。 &lt;Ctrl&gt;&lt;b&gt; 視窗往上捲一頁。 &lt;Ctrl&gt;&lt;d&gt; 視窗往下捲半頁。 &lt;Ctrl&gt;&lt;u&gt; 視窗往上捲半頁。 &lt;Ctrl&gt;&lt;e&gt; 視窗往下捲一行。 &lt;Ctrl&gt;&lt;y&gt; 視窗往上捲一行。 刪除、複製及修改指令介紹 (此單元較少使用)d(delete)、c(change)和y(yank)這一類的指令在 vi 中的指令格式為： Operator + Scope = command (運算子) (範圍) 運算子： d 刪除指令。刪除資料，但會將刪除資料複製到記憶體緩衝區。 y 將資料(字組、行列、句子或段落)複製到緩衝區。 p 放置(put)指令，與 d 和 y 配和使用。可將最後delete或yank的資 料放置於游標所在位置之行列下。 c 修改(change)指令，類似delete與insert的組和。刪除一個字組、句 子等之資料，並插入新鍵資料。 範圍： e 由游標所在位置至該字串的最後一個字元。 w 由游標所在位置至下一個字串的第一個字元。 b 由游標所在位置至前一個字串的第一個字元。 $ 由游標所在位置至該行的最後一個字元。 0 由游標所在位置至該行的第一個字元。 ) 由游標所在位置至下一個句子的第一個字元。 ( 由游標所在位置至該句子的第一個字元。 { 由游標所在位置至該段落的最後一個字元。 } 由游標所在位置至該段落的第一個字元。 整行動作 dd 刪除整行。 D 以行為單位，刪除游標後之所有字元。 cc 修改整行的內容。 yy yank整行，使游標所在該行複製到記憶體緩衝區。 刪除與修改x 刪除游標所在該字元。 X 刪除游標所在之前一字元。 dd 刪除游標所在該行。 r 用接於此指令之後的字元取代(replace)游標所在字元。 如： ra 將游標所在字元以 a 取代之。 R 進入取代狀態，直到&lt;ESC&gt;為止。 s 刪除游標所在之字元，並進入輸入模式直到&lt;ESC&gt;。 S 刪除游標所在之該行資料，並進入輸入模式直到&lt;ESC&gt;。 搬移與複製利用 delete 及 put 指令可完成資料搬移之目的。 利用 yank 及 put 指令可完成資料複製之目的。 yank 和 delete 可將指定的資料複製到記憶體緩衝區，而藉由 put 指令 可將緩衝區內的資料複製到螢幕上。 例： 搬移一行 ‧在該行執行 dd ‧游標移至目的地 ‧執行 p 複製一行 ‧在該行執行 yy ‧游標移至目的地 ‧執行 p 指令重複在指令模式中，可在指令前面加入一數字 n，則此指令動作會重複執行 n 次。 例： 刪除10行 ‧10dd 複製10行 ‧10yy ‧游標移至目的地 ‧p 指標往下移10行 ‧10j 取消前一動作(Undo)即復原執行上一指令前的內容。 u 恢復最後一個指令之前的結果。 U 恢復游標該行之所有改變。 搜尋在vi中可搜尋某一字串，使游標移至該處。 /字串 往游標之後尋找該字串。 ?字串 往游標之前尋找該字串。 n 往下繼續尋找下一個相同的字串。 N 往上繼續尋找下一個相同的字串。 資料的連接J 句子的連接。將游標所在之下一行連接至游標該行的後面。 若某行資料太長亦可將其分成兩行，只要將游標移至分開點，進入輸入模式 (可利用 a、i等指令)再按&lt;Enter&gt;即可。 環境的設定：set nu 設定資料的行號。 ：set nonu 取消行號設定。 ：set ai 自動內縮。 ：set noai 取消自動內縮。 自動內縮(automatic indentation) 在編輯文件或程式時，有時會遇到需要內縮的狀況，『：set ai』即提供自 動內縮的功能，用下例解釋之： ‧vi test ‧(進入編輯視窗後) this is the test for auto indent &lt;Tab&gt;start indent ← ：set ai (設自動內縮) &lt;Tab&gt;data &lt;Tab&gt;data &lt;Tab&gt;data ← ：set noai (取消自動內縮) the end of auto indent. ‧註：&lt;Ctrl&gt;&lt;d&gt; 可刪除&lt;Tab&gt;字元。 ex指令讀寫資料 ：w 將緩衝區的資料寫入磁碟中。 ：10,20w test 將第10行至第20行的資料寫入test檔案。 ：10,20w&gt;&gt;test 將第10行至第20行的資料加在test檔案之後。 ：r test 將test檔案的資料讀入編輯緩衝區的最後。 刪除、複製及搬移 ：10,20d 刪除第10行至第20行的資料。 ：10d 刪除第10行的資料。 ：%d 刪除整個編輯緩衝區。 ：10,20co30 將第10行至第20行的資料複製至第30行之後。 ：10,20mo30 將第10行至第20行的資料搬移至第30行之後。 字串搜尋與取代 s(substitute)指令可搜尋某行列範圍。 g(global)指令則可搜尋整個編輯緩衝區的資料。 s指令以第一個滿足該條件的字串為其取代的對象，若該行有數個滿足該條 件的字串，也僅能取代第一個，若想取代所有的字串則需加上g參數。 ：1,$s/old/new/g 將檔案中所有的『old』改成『new』。 ：10,20s/^/ / 將第10行至第20行資料的最前面插入5個空白。 ：%s/old/new/g 將編輯緩衝區中所有的『old』改成『new』。 恢復編輯時被中斷的檔案在編輯過程中，若系統當掉或連線中斷，而緩衝區的資料並還未 被寫回磁碟時，當再度回到系統，執行下列指令即可回復中斷前 的檔案內容。 %vi -r filename 編輯多個檔案vi亦提供同時編輯多個檔案的功能，方法如下： %vi file1 file2 .. 當第一個檔案編修完成後，可利用『：w』將該緩衝區存檔，而後 再利用 『：n』載入下一個檔案。]]></content>
    </entry>

    
    <entry>
      <title><![CDATA[优化wireshark下Lua插件SMGP协议代码]]></title>
      <url>%2F2016%2F12%2F02%2Fwireshark%2FSMGP3_Lua_wireshark%2F</url>
      <content type="text"><![CDATA[优化wireshark下Lua插件SMGP3.0协议代码@(Linux)[学习] [toc] 写在前面由于wireshark对SMGP协议不支持，之前使用wireshark查看SMGP协议字段，一般都是拷贝下来HEX，一个字节一个字节对。眼睛都要花了！昨天检查问题的时候同事和我说wireshark可以支持Lua插件自己编写协议识别代码，然后给了我一个SMGP.Lua文件。我安装了一下，发现是可以识别，但是如果一个包里有多个协议包的时候只识别一个，于是决定优化一下 2016-12-29修改有时候包经过跳转，则端口不是标准的8890了，则可以在后面添加一行代码：12tcp_table:add(8890,p_SMGP)tcp_table:add(38080,p_SMGP) 这样就可以识别8890和38080了。想要识别什么就添加什么。很方便 前期准备Lua方面首先，我对Lua语言之前没有接触过，不过语言大都差不多。而且我的修改比较简单，应该就是加一个控制循环语句和判断。先去看了一下Lua一些基本语法.lua的循环和shell差不多123while a do passend sireshark方面根据官方给的实例，搞懂基本流程https://www.wireshark.org/docs/wsdg_html_chunked/lua_module_Pinfo.html#lua_class_Column https://www.wireshark.org/docs/wsdg_html_chunked/PartDevelopment.html要改哪里就去搜索开发文档 主要修改地方找到主函数在主函数下添加根据字长是否还有剩余，进行判断，如果还有数据，则接着执行123456789101112131415161718192021function p_SMGP.dissector(buf,pkt,root) -- if SMGP_dissector(buf,pkt,root) then -- else -- data_dis:call(buf,pkt,root) --将下面那段替换上面的那段 --从这里开始 local buf_len = buf:len() local p_length = SMGP_dissector(buf,pkt,root) --p_length表示匹配到的有效协议包字段长度 local shengyu_length = buf_len-p_length --表示剩余需要匹配的长度 ---------如果剩余长度大于8字节，则接着匹配 while shengyu_length &gt; 8 do p_length = SMGP_dissector(buf(p_length,shengyu_length),pkt,root) shengyu_length = shengyu_length-p_length end if shengyu_length == 0 then -- else data_dis:call(buf(p_length,shengyu_length),pkt,root) --到这里结束 end end 修改上面后还要修改返回值，之前函数是返回布尔型的，让他返回有效长度，修改SMGP_dissector函数12345678 local function SMGP_dissector(buf,pkt,root) local buf_len = buf:len();--if buf_len &lt; 8 then return false end if buf_len &lt; 8 then return 0 end --修改返回值为字段长度，0表示有效协议字段长度为0 -----省略----- --return true return v_length --修改返回值 end 初步完工修改上面之后，基本上可以识别了多个协议包了但是我发现submit包里面本来是有一个8字节的保留字段的，这个字段主要是用于长短信设置udhi字段的。而这个代码里面没有，所以可以添加。1234567local f_RecvTime = ProtoField.string("SMGP.RecvTime","RecvTime")--添加定义保留字段 local f_Reserve = ProtoField.uint32("SMGP.Reserve","Reserve",base.HEX,&#123; [0x0001]="TP_pid",[0x0002]="TP_udhi"--, -- [0x0003]="" &#125;) local f_ReserveValue = ProtoField.uint32("SMGP.ReserveValue","ReserveValue",base.HEX) 先在前面一大段定义后面添加一个定义然后在p_SMGP.fields字段后面添加添加的f_RecvTime 如果要完善，f_ReserveValue字段应该是定义函数的这里偷了个懒，以后可能添加 然后在local function SMGP_Submit(buf,pkt,t)函数下面添加123456local function SMGP_Submit(buf,pkt,t)---省略-----添加调用保留字段 t:add(f_Reserve,buf(139+v_msgLen,2)) t:add(f_ReserveValue,buf(141+v_msgLen,6)) end 最后一点在高亮部分的info里面显示里面的包的协议类型这个我找了一上午，主要是要找怎样添加字段，而之前的用set()函数是重置一般是用append()函数，但是，这个是添加到字段尾部，我想添加到头部google了很久，英文的又看不懂。。。最后还是在官方api里找到了，用preend()函数我也可以说我是看英文官方文档的人了再各个协议包字段函数里面添加对应的显示字段1pkt.cols.info:prepend("SMGP_Submit" .. " ") 顺便添加了一下Active_Test和Active_TestResp的显示到这里，基本上已经改好了，可以适用于大多数的SMGP协议包了。之后有可能进行修改吧。 安装既然这么好，那么，哪里可以用上呢？先升级wireshark，我也忘了哪个版本支持Lua了，看帮助吧，里面有。然后在安装目录里面的init.lua文件最后添加一行1dofile(DATA_DIR.."SMGP.lua") 然后将后面的代码复制，粘贴到一个新文件SMGP.lua,放到init.lua同级目录就可以用了 修改后代码123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209-- SMGP.lua-- SMGP3.0 protocol-- author: summingyu--基于h_Davy代码----https://www.wireshark.org/docs/wsdg_html_chunked/lua_module_Pinfo.html#lua_class_Column--https://www.wireshark.org/docs/wsdg_html_chunked/PartDevelopment.htmldo local p_SMGP = Proto("SMGP","SMGP","SMGP Protocol") local f_Length = ProtoField.uint32("SMGP.length","Packet Length",base.DEC) local f_CommandId = ProtoField.uint32("SMGP.RequestId","Request ID",base.HEX,&#123; [1]="Login", [0x80000001]="LoginResp", [2]="Submit", [0x80000002]="SubmitResp", [3]="Deliver", [0x80000003]="DeliverResp", [4]="ActiveTest", [0x80000004]="ActiveTestResp", [5]="Forward", [0x80000005]="ForwardResp", [6]="Exit", [0x80000006]="ExitResp", [7]="Query", [0x80000007]="QueryResp"&#125;) local f_SequenceId = ProtoField.uint32("SMGP.sequenceId","Sequence ID",base.DEC); local f_ClientID = ProtoField.string("SMGP.ClientID","ClientID") local f_Authenticator = ProtoField.bytes("SMGP.Authenticator","Authenticator") local f_LoginMode = ProtoField.uint8("SMGP.LoginMode","Login Mode",base.DEC) local f_TimeStamp = ProtoField.uint32("SMGP.TimeStamp","TimeStamp",base.DEC) local f_Version = ProtoField.uint8("SMGP.Version","Version",base.HEX) local f_Status = ProtoField.uint32("SMGP.Status","Status",base.DEC,&#123;[0]="OK"&#125;) local f_MsgType = ProtoField.uint32("SMGP.MsgType","MsgType",base.DEC,&#123;[0]="MO",[6]="MT",[7]="P2P"&#125;) local f_NeedReport = ProtoField.uint32("SMGP.NeedReport","NeedReport",base.DEC,&#123;[0]="N",[1]="Y"&#125;) local f_Priority = ProtoField.uint32("SMGP.Priority","Priority",base.DEC) local f_ServiceID = ProtoField.string("SMGP.ServiceID","ServiceID") local f_FeeType = ProtoField.string("SMGP.FeeType","FeeType") local f_FeeCode = ProtoField.string("SMGP.FeeCode","FeeCode") local f_FixedFee = ProtoField.string("SMGP.FixedFee","FixedFee") local f_MsgFormat = ProtoField.uint32("SMGP.MsgFormat","MsgFormat",base.DEC,&#123; [0]="ASCII",[3]="Card",[4]="Binary",[8]="UCS2",[15]="GB18030",[246]="SIM"&#125;) local f_ValidTime = ProtoField.string("SMGP.ValidTime","ValidTime") local f_AtTime = ProtoField.string("SMGP.AtTime","AtTime") local f_SrcTermID = ProtoField.string("SMGP.SrcTermID","SrcTermID") local f_ChargeTermID = ProtoField.string("SMGP.ChargeTermID","ChargeTermID") local f_DestTermIDCount = ProtoField.uint32("SMGP.DestTermIDCount","DestTermIDCount",base.DEC) local f_DestTermID = ProtoField.string("SMGP.DestTermID","DestTermID") local f_MsgLength = ProtoField.uint8("SMGP.MsgLength","MsgLength",base.DEC) local f_MsgContent = ProtoField.string("SMGP.MsgContent","MsgContent") local f_MsgID = ProtoField.bytes("SMGP.MsgID","MsgID") local f_IsReport = ProtoField.uint8("SMGP.IsReport","IsReport",base.DEC) local f_RecvTime = ProtoField.string("SMGP.RecvTime","RecvTime") --添加定义保留字段 local f_Reserve = ProtoField.uint32("SMGP.Reserve","Reserve",base.HEX,&#123; [0x0001]="TP_pid",[0x0002]="TP_udhi"--, -- [0x0003]="" &#125;) local f_ReserveValue = ProtoField.uint32("SMGP.ReserveValue","ReserveValue",base.HEX) -- p_SMGP.fields = &#123;f_Length,f_CommandId,f_SequenceId,f_ClientID,f_Authenticator, f_LoginMode,f_TimeStamp,f_Version,f_Status,f_MsgType,f_NeedReport,f_Priority, f_ServiceID,f_FeeType,f_FeeCode,f_FixedFee,f_MsgFormat,f_ValidTime,f_AtTime, f_SrcTermID,f_ChargeTermID,f_DestTermIDCount,f_DestTermID,f_MsgLength,f_MsgContent, f_MsgID,f_IsReport,f_RecvTime,f_Reserve,f_ReserveValue&#125; local data_dis = Dissector.get("data") -- local function SMGP_Login(buf,pkt,t) t:add(f_ClientID,buf(12,8)) t:add(f_Authenticator,buf(20,16)) t:add(f_LoginMode,buf(36,1)) t:add(f_TimeStamp,buf(37,4)) t:add(f_Version,buf(41,1)) pkt.cols.info:prepend("SMGP_Login;" .. " ") --添加在info栏显示包类型 end -- local function SMGP_LoginResp(buf,pkt,t) t:add(f_Status,buf(12,4)) t:add(f_Authenticator,buf(16,16)) t:add(f_Version,buf(32,1)) pkt.cols.info:prepend("SMGP_LoginResp;" .. " ") end -- local function SMGP_Submit(buf,pkt,t) t:add(f_MsgType,buf(12,1)) t:add(f_NeedReport,buf(13,1)) t:add(f_Priority,buf(14,1)) t:add(f_ServiceID,buf(15,10)) pkt.cols.info:prepend("SMGP_Submit" .. " ") t:add(f_FeeType,buf(25,2)) t:add(f_FeeCode,buf(27,6)) t:add(f_FixedFee,buf(33,6)) t:add(f_MsgFormat,buf(39,1)) t:add(f_ValidTime,buf(40,17)) t:add(f_AtTime,buf(57,17)) t:add(f_SrcTermID,buf(74,21)) t:add(f_ChargeTermID,buf(95,21)) t:add(f_DestTermIDCount,buf(116,1)) t:add(f_DestTermID,buf(117,21)) local v_msgLen = buf(138,1) t:add(f_MsgLength,v_msgLen) v_msgLen = v_msgLen:uint() t:add(f_MsgContent,buf(139,v_msgLen)) --添加调用保留字段 t:add(f_Reserve,buf(139+v_msgLen,2)) t:add(f_ReserveValue,buf(141+v_msgLen,6)) end --local function SMGP_SubmitResp(buf,pkt,t) t:add(f_MsgID,buf(12,10)) t:add(f_Status,buf(22,4)) pkt.cols.info:prepend("SMGP_SubmitResp;" .. " ")end local function SMGP_DelvResp(buf,pkt,t) t:add(f_MsgID,buf(12,10)) t:add(f_Status,buf(22,4)) pkt.cols.info:prepend("SMGP_DelvResp;" .. " ") end -- local function SMGP_Deliver(buf,pkt,t) t:add(f_MsgID,buf(12,10)) local v_IsReport = buf(22,1) t:add(f_IsReport,v_IsReport) pkt.cols.info:prepend("SMGP_Deliver;" .. " ") v_IsReport = v_IsReport:uint() t:add(f_MsgFormat,buf(23,1)) t:add(f_RecvTime,buf(24,14)) t:add(f_SrcTermID,buf(38,21)) t:add(f_DestTermID,buf(59,21)) local v_msgLen = buf(80,1) t:add(f_MsgLength,v_msgLen) v_msgLen = v_msgLen:uint() if v_IsReport == 1 then -- t:add(f_MsgID,buf(84, 10)):append_text(' (Submit MsgID)') t:add(f_MsgContent,buf(94,v_msgLen-13)) else t:add(f_MsgContent,buf(81,v_msgLen)) end end -- local function SMGP_ActiveTest( buf,pkt,root ) pkt.cols.info:prepend("SMGP_ActiveTest;" .. " ") end -- local function SMGP_ActiveTestResp( buf,pkt,root ) pkt.cols.info:prepend("SMGP_ActiveTestResp;" .. " ") end -- local function SMGP_dissector(buf,pkt,root) local buf_len = buf:len();--if buf_len &lt; 8 then return false end if buf_len &lt; 8 then return 0 end --修改返回值为字段长度，0表示有效协议字段长度为0 local v_length = buf(0,4) v_length = v_length:uint() local v_command = buf(4,4) local v_sequenceId = buf(8,4) pkt.cols.protocol = "SMGP" local t = root:add(p_SMGP,buf(0,buf_len)) t:add(f_Length,v_length) t:add(f_CommandId,v_command) t:add(f_SequenceId,v_sequenceId) -- v_command = v_command:uint() if v_command == 1 then SMGP_Login(buf,pkt,t) elseif v_command == 2 then SMGP_Submit(buf,pkt,t) elseif v_command == 3 then SMGP_Deliver(buf,pkt,t) elseif v_command == 4 then SMGP_ActiveTest(buf,pkt,t) elseif v_command == 0x80000001 then SMGP_LoginResp(buf,pkt,t) elseif v_command == 0x80000002 then SMGP_SubmitResp(buf,pkt,t) elseif v_command == 0x80000003 then SMGP_DelvResp(buf,pkt,t) elseif v_command == 0x80000004 then SMGP_ActiveTestResp(buf,pkt,t) elseif v_command &gt; 0x80000000 then -- else t:add(f_Data,buf(20,buf_len-20)) end --return true return v_length --修改返回值 end -- function p_SMGP.dissector(buf,pkt,root) -- if SMGP_dissector(buf,pkt,root) then -- else -- data_dis:call(buf,pkt,root) --将下面那段替换上面的那段 --从这里开始 local buf_len = buf:len() local p_length = SMGP_dissector(buf,pkt,root) --p_length表示匹配到的有效协议包字段长度 local shengyu_length = buf_len-p_length --表示剩余需要匹配的长度 ---------如果剩余长度大于8字节，则接着匹配 while shengyu_length &gt; 8 do p_length = SMGP_dissector(buf(p_length,shengyu_length),pkt,root) shengyu_length = shengyu_length-p_length end if shengyu_length == 0 then -- else data_dis:call(buf(p_length,shengyu_length),pkt,root) --到这里结束 end end tcp_table = DissectorTable.get("tcp.port") tcp_table:add(8890,p_SMGP) tcp_table:add(38080,p_SMGP)end]]></content>
    </entry>

    
    <entry>
      <title><![CDATA[利用pyenv和virtualenv搭建多版本pyhton虚拟环境]]></title>
      <url>%2F2016%2F11%2F28%2Fpython%2Fpyenv%2F</url>
      <content type="text"><![CDATA[写在前面之前看到python公众号一篇文章，说建议2020年之后停止python2版本的维护，转移到python3上，但是现在大多数还是使用的python2，所以如果转移到python3上要进行python3的学习，免不了要在机器上安装多个版本的python，这时候如何使各个版本相互独立是个问题。所以在网上找了一下资料.http://www.it165.net/pro/html/201405/13603.html 安装pyenv和pyenv-virtualenv使用下面命令进行安装1curl https://raw.github.com/yyuu/pyenv-installer/master/bin/pyenv-installer | bash 这个里面集成了pyenv和pyenv-virtualenv插件也可以参照github上官方pyenv和pyenv-virtualenv安装 配置环境变量 将下面配置写入到~/.bash_profile文件 123456export PYENV_ROOT=&quot;$&#123;HOME&#125;/.pyenv&quot;if [ -d &quot;$&#123;PYENV_ROOT&#125;&quot; ]; then export PATH=&quot;$&#123;PYENV_ROOT&#125;/bin:$&#123;PATH&#125;&quot; eval &quot;$(pyenv init -)&quot;fi 或者 执行下面语句(使用官方配置) 1234echo &apos;export PYENV_ROOT=&quot;$HOME/.pyenv&quot;&apos; &gt;&gt; ~/.bash_profileecho &apos;export PATH=&quot;$PYENV_ROOT/bin:$PATH&quot;&apos; &gt;&gt; ~/.bash_profileecho &apos;eval &quot;$(pyenv init -)&quot;&apos; &gt;&gt; ~/.bash_profileecho &apos;eval &quot;$(pyenv virtualenv-init -)&quot;&apos; &gt;&gt; ~/.bash_profile 注意：ubuntu和Fedora系统是写入到~/.bashsrc文件 使配置文件生效可以选择退出登陆再登陆，也可以使用source ~/.bash_profile命令来重新加载环境变量 安装多个python版本使用pyenv可以安装多个版本。先查看可以安装的版本1pyenv install --list 找到自己想要安装的版本号12pyenv install 2.7.12pyenv install 3.5.2 安装完毕后使用pyenv versions查看所有版本使用pyenv version查看当前激活版本 切换版本测试使用pyenv global 2.7.12,就切换版本到2.7.12了使用pyenv global system切换回系统版本卸载某个版本，使用pyenv uninstall 2.7.12就卸载了2.7.12的版本 利用virtualenv创建虚拟环境virtualenv是一个独立的程序，可以使用sudo pip install virtualenv下载安装使用上面步骤安装的pyenv则自带virtualenv插件，不用安装。 先来创建一个2.7的环境12pyenv virtualenv 2.7.12 env2.7.12 # env2.7.1是标识，可以随便取，自己方便记就行 表示创建了一个虚拟环境，evn2.7.12 使用pyenv activate evn2.7.12将切换到evn2.7.12虚拟环境中，会看到前面出现了(evn2.7.12)标识，表示在虚拟环境中，在此环境中可以随便修改，而不用担心搞乱系统版本. 要想切换回系统环境，使用 pyenv deactivate就可以退出虚拟环境.如果想要删除虚拟环境，直接使用1rm -rf ~/.pyenv/versions/env2.7.12/ 就可以删除]]></content>
    </entry>

    
    <entry>
      <title><![CDATA[记录登陆与操作日志]]></title>
      <url>%2F2016%2F11%2F23%2Flinux%2FLoginlog%2F</url>
      <content type="text"><![CDATA[写在前面记录登陆者的ip，登陆执行操作和登陆时间，登陆一次记录一次原理是将命令写在/etc/profile里面，每次登陆都会加载/etc/profile文件，所以能够记录 手动创建在/etc/profile文件后面加上下面代码init.txt123456789101112131415161718192021222324252627282930313233343536#登陆时运行export LOGINLOGDIR=/home/LoginLog/history#PS1="`whoami`@`hostname`:"'[$PWD]'#export HISTTIMEFORMAT="%F %T"#historyexport HISTTIMEFORMAT="[%Y.%m.%d %H:%M:%S]"USER_IP=`who -u am i 2&gt;/dev/null| awk '&#123;print $NF&#125;'|sed -e 's/[()]//g'`if [ "$USER_IP" = "" ]thenUSER_IP=`hostname`fiif [ ! -d $&#123;LOGINLOGDIR&#125; ]then mkdir -p $&#123;LOGINLOGDIR&#125; chmod 733 $&#123;LOGINLOGDIR&#125;fiif [ ! -d $&#123;LOGINLOGDIR&#125;/$&#123;LOGNAME&#125; ]then mkdir $&#123;LOGINLOGDIR&#125;/$&#123;LOGNAME&#125; chmod 300 $&#123;LOGINLOGDIR&#125;/$&#123;LOGNAME&#125;fiif [ ! -d /home/LoginLog/bin/ ]then mkdir /home/LoginLog/bin/ else /bin/bash /home/LoginLog/bin/Login.shfiexport HISTSIZE=4096DT=`date +"%Y%m%d_%H%M%S"`export LOGINDT=$&#123;LOGINLOGDIR&#125;/LOGINLOG_`date +"%Y%m%d_%H%M"`export HISTFILE="$&#123;LOGINLOGDIR&#125;/$&#123;LOGNAME&#125;/$&#123;USER_IP&#125;_history.$DT"chmod 600 $&#123;LOGINLOGDIR&#125;/$&#123;LOGNAME&#125;/*history* 2&gt;/dev/null 在/home/LoginLog/bin目录创建Login.sh123456789101112131415161718192021#!/bin/bashMONTH=`date +"%Y%m"`DAY=`date +"%d"`HOUR=`date +"%H"`MIN=`date +"%M"`NOW=$&#123;MONTH&#125;$&#123;DAY&#125;_$&#123;HOUR&#125;_$&#123;MIN&#125;LOGINLOGDIR=/home/LoginLog/historyLOGDIR=$&#123;LOGINLOGDIR&#125;/$&#123;LOGNAME&#125;/LOGINif [ ! -d $&#123;LOGDIR&#125; ]thenmkdir -p $&#123;LOGDIR&#125;fiLOGFILE=$&#123;LOGDIR&#125;/Loginlog_$&#123;NOW&#125;.logif [ ! -f $&#123;LOGFILE&#125; ]thentouch $&#123;LOGFILE&#125;chmod 600 $&#123;LOGFILE&#125;fiecho "==============`date`================="&gt;&gt; $&#123;LOGFILE&#125;last -x|head &gt;&gt; $&#123;LOGFILE&#125; 编写删除脚本DelLoginLog.sh1234567891011121314151617181920212223242526272829303132333435#!/bin/bash#script name:DelLoginLog.shexport LANG=enLOGINLOGDELDIR=/home/LoginLogLOGINLOGDIR=/home/LoginLog/history#删除90天前的所有文件find $&#123;LOGINLOGDIR&#125; -mtime +90 -type f|xargs rm -f#读取日志文件大小FREEDISK=`du -sk $&#123;LOGINLOGDELDIR&#125;/|awk '&#123;print $1&#125;'`function DiskClear()&#123; #查找1天前的最早的10个文件 HEADMOST=`find $&#123;LOGINLOGDELDIR&#125; -mtime +1 -type f|xargs ls -lrt|awk '&#123;print $NF&#125;'|egrep -v "total$|sh$|tmp$|^snapshot$"|head -n 10`; #如果文件数为0，则退出函数 HEADCOUNT=`find $&#123;LOGINLOGDELDIR&#125; -mtime +1 -type f|egrep -v "total$|sh$|tmp$|^snapshot$"|wc -l`; [ "$&#123;HEADCOUNT&#125;" == '0' ] &amp;&amp; return; rm -f "$HEADMOST"; FREEDISK=`du -sk $&#123;LOGINLOGDIR&#125;/|awk '&#123;print $1&#125;'`; if [ "$&#123;FREEDISK&#125;" -ge "102400" ];then DiskClear; fi; &#125;# 当文件大于1G时删除if [ "$&#123;FREEDISK&#125;" -ge "102400" ];then DiskClearfi#删除空文件夹EMPTYDIRCOUNT=`find $&#123;LOGINLOGDELDIR&#125; -type d -empty|wc -l`if [ $EMPTYDIRCOUNT != '0' ];then find $&#123;LOGINLOGDELDIR&#125; -type d -empty|xargs rmdir -p --ignore-fail-on-non-emptyfi 备份并上传脚本LoginLogBakup.sh — —目前没部署123456789101112131415161718192021222324252627282930313233343536373839404142434445#!/bin/bashBAKUPDIR=/home/LoginLog/BakLOGINLOGDIR=/home/LoginLog/historyMONTH=`date +"%Y%m"`DAY=`date +"%d"`HOUR=`date +"%H"`MIN=`date +"%M"`NOW=$&#123;MONTH&#125;$&#123;DAY&#125;_$&#123;HOUR&#125;_$&#123;MIN&#125;BAKUPFILE=$&#123;BAKUPDIR&#125;/backup_$&#123;NOW&#125;.tar.gzif [ ! -d $&#123;BAKUPDIR&#125; ];then mkdir -p $&#123;BAKUPDIR&#125;ficd $&#123;BACUPDIR&#125;tar -g snapshot -zcf $&#123;BAKUPFILE&#125; $&#123;LOGINLOGDIR&#125;##############################ftp#########################################FTPlog=$&#123;BAKUPDIR&#125;/ftp_`date +%Y-%m-%d`.logTOHOST=HOSTPORT=USER=PASSWORD=TODIR=echo "`date +%Y-%m-%d' '%H:%M:%S`,***FTP***Begin to put files....." &gt;&gt; $FTPlog/usr/bin/ftp -n &lt;&lt; ! &gt; /dev/nullopen $&#123;TOHOST&#125; $&#123;HOSTPORT&#125;user $&#123;USER&#125; $&#123;PASSWORD&#125;binarycd $&#123;TODIR&#125;put $&#123;BAKUPFILE&#125; $&#123;BAKUPFILE&#125;.$rename $&#123;BAKUPFILE&#125;.$ $BAKUPFILEbye!if [ $? = 0 ]; then echo "`date +%Y-%m-%d' '%H:%M:%S`,***FTP***put $i sucess...." &gt;&gt; $FTPlogelse echo "`date +%Y-%m-%d' '%H:%M:%S`,***FTP***put $i failed...." &gt;&gt; $FTPlogfiecho "`date +%Y-%m-%d' '%H:%M:%S`,***FTP***End to put files....." &gt;&gt; $FTPlog 修改脚本权限在crontab -e中添加定时任务将DelLoginLog.sh和LoginLogBakup.sh脚本加入定时任务 */5 * * * * /bin/bash /home/LoginLog/bin/DelLoginLog.sh 要读取历史日志时间时执行下面代码进行时间格式转换12FILENAME=192.168.153.1_history.20160524_205143perl -i -pe 's/^#(\d+)$/localtime($1)/e' $&#123;FILENAME&#125; 注意 新建目录和文件时注意权限 脚本权限要加x ：chmod a+x **.sh $LOGINLOGDIR 目录权限要可写可执行，可以不给其他用户读取权限：chmod 733 自动创建####自动安装脚本setup.sh12345678910111213141516171819202122232425262728293031#!/bin/bash## 检查 root 权限[ $(id -g) != "0" ] &amp;&amp; die "Script must be run as root.";cat ./init.txt &gt;&gt; /etc/profilelogdir=/home/LoginLogLOGINLOGDIR=$&#123;logdir&#125;/historyif [ ! -d $&#123;logdir&#125; ]then mkdir -p $&#123;logdir&#125; chmod 733 $&#123;logdir&#125;fiif [ ! -d $&#123;LOGINLOGDIR&#125; ]then mkdir -p $&#123;LOGINLOGDIR&#125; chmod 733 $&#123;LOGINLOGDIR&#125;fiif [ ! -d $&#123;logdir&#125;/bin/ ]then mkdir $&#123;logdir&#125;/bin/fichmod 744 ./bin/*.shchmod a+x ./bin/Login.shcp ./bin/*.sh $&#123;logdir&#125;/bin/#添加定时任务echo "5 3 * * * /bin/bash $&#123;logdir&#125;/bin/DelLoginLog.sh" &gt;&gt; /var/spool/cron/root 注意：在安装脚本目录执行安装脚本打包文件内容清单1234567autosetup.tar.gz|--autosetup/ |--bin/ |--DelLoginLog.sh |--Login.sh |--init.txt |--setup.sh autosetup.tar.gz 注意首次执行完要exit退出，]]></content>
    </entry>

    
    <entry>
      <title><![CDATA[用ssh实现hexo免输密码上传文章]]></title>
      <url>%2F2016%2F11%2F18%2Fhexo%2F%E4%BD%BF%E7%94%A8ssh%E5%AE%9E%E7%8E%B0hexo%E5%85%8D%E8%BE%93%E5%AF%86%E7%A0%81%E4%B8%8A%E4%BC%A0%E6%96%87%E7%AB%A0%2F</url>
      <content type="text"><![CDATA[写在前面最近几天一直在修修改改配置文件，每次hexo d都要输一遍用户名密码，心累。就到网上找了一下教程，怎么实现不要输密码，其实就是在github这个仓库里面添加公钥就行 1、客户端生成密钥对在客户端执行下面的命令12ssh-keygen -t rsa -C "summingbest@gmail.com" #邮箱填你自己的github邮箱# 然后会有几个要输入的地方，直接回车就行 执行完成之后cd ~/.ssh到你用户目录下面的.ssh目录里，你会看到两个文件12[summingyu@localhost .ssh]$ lsid_rsa id_rsa.pub 这两个文件就是你的公私钥了。然后cat id_rsa.pub将里面的内容复制,如下1ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAw7/rIO8jBbejKOvZdlZtxC8K3OMuFeC28AnVQoZckRQxivtBkqXeg8cPGBF54UMaQVkMXpaYrfBg+WpjZjqO/V7g33ePCicNBr+7rUXznD2hiSEFDknESuGujtSWgoayfV3u+qkAcBXxL7WvG4kizd6DYq/Tf/6ZHcOQavzpobr52u8NysUkrAV8ZSO9Dl306msfkVhfi/QdkXIC4X27QXoFm5hguY/JmNCI9mHal5h1+a1qr2m+iUidR1rOUGmcQ1o2tmlDDbdu9E1YpMsxeLUz/XmUs3pCEgobSPpl4XjAMxgJ8uutI2270olh5gJOYPW32eN5ixTpR5Wir+JQYQ== summingbest@gmail.com 2、添加公钥到github页面进入你的github博客仓库的设置页下面的deploy keys页面看到哪个熟悉的图标了吗？点击一下你就能新建key了，如果不嫌烦的话，还可以删除了再添加(neta科技美学)随便取个什么标题，将在客户端上复制的公钥粘贴到下面的key里面，勾选Allow write access选项，点add key。密钥对就添加完成了 3、测试在客户端执行命令ssh -T git@github.com12[summingyu@localhost .ssh]$ ssh -T git@github.comHi summingyu/summingyu.github.io! You've successfully authenticated, but GitHub does not provide shell access. 如果看到上面的结果，那么就说明通了。 4、修改配置文件最后，修改站点配置文件_config.yml在上一篇文章hexo搭建自己的博客 中讲到最后添加的一行代码进行如下修改1234deploy: type: git# repo: https://github.com/summingyu/summingyu.github.io.git repo: git@github.com:summingyu/summingyu.github.io.git 将原来的https链接修改成ssh的链接进行了以上配置，基本就可以了。反正我是这样搞好的]]></content>
    </entry>

    
    <entry>
      <title><![CDATA[hexo搭建自己的博客]]></title>
      <url>%2F2016%2F11%2F17%2Fhexo%2Fhexo%E6%90%AD%E5%BB%BA%E8%87%AA%E5%B7%B1%E7%9A%84%E5%8D%9A%E5%AE%A2%2F</url>
      <content type="text"><![CDATA[写在前面以前就一直想建一个博客写点东西记录生活装逼，最近买了个vps，就想搭建一个博客。然后上网根据教程，好歹搭建起来了。能用就行，后期优化吧。我是参照5分钟 搭建免费个人博客和hexo官方文档搭建的，使用的是linux centos6系统,window的安装百度就行 准备1. 准备一个github的域名和仓库 注册github账户 建立仓库创建一个你自己的仓库，命名为username.github.io例如，我的仓库名就是summingyu.github.io,这个username一定要与你前面的Owner一致 2. 搭建环境安装hexo要先安装git(用来同步本地页面和github仓库),nodejs 安装git 如果有配置yum源，直接使用yum安装1yum -y install git 没有yum，配置yum之后用yum安装括弧笑 下载源码编译安装。最新源码地址:https://github.com/git/git/releases例如现在最新版本为2.11.0-rc1123456789wget https://github.com/git/git/archive/v2.11.0-rc1.tar.gz# 得到一个源码包，解压tar xvf v2.11.0-rc1.tar.gzcd v2.11.0-rc1#编译安装，一下步骤一步一步来autoconf./configuremakemake install 然后修改/etc/ld.so.conf文件，在最后一行添加1/usr/local/lib 如果有就不用添加了。这时候就安装好了，查看一下版本：12[summingyu@localhost source]$git --versiongit version 2.11.0.rc1 发现已经是最新的版本了。 注意：如果以前安装了低版本的git，要重新加载一下~/.bash_profile文件1source ~/.bash_profile 安装nodejs 安装nvm，是nodejs的版本管理器，可以轻松切换版本1$ curl https://raw.github.com/creationix/nvm/master/install.sh | sh 安装完成后重启终端或者重新加载配置文件source ~/.bash_profile，测试nvm看是否有命令，如果有，那就安装成功了 安装nodejs1nvm install 4 安装hexo如果上面的都安装成功了，那么就可以安装hexo了.执行命令1npm install hexo-cli -g 以上都完成了的话，那么环境就搭建好了 hello,world都部署完了的话，就写一篇hello,world吧！毕竟程序员都会 初始化博客执行下面的命令,下面的username.github.io就是上面你在github上创建的仓库1hexo init username.github.io 修改配置主题安装目前流行的是使用next极简主题12cd username.github.iogit clone https://github.com/iissnan/hexo-theme-next themes/next 基础配置hexo有官方指定的配置文档https://hexo.io/zh-cn/docs/configuration.html查看上面的配置，想配啥配啥。下面列出主要配置123456789101112title: 余苏明的幻想乡 #博客名称subtitle: summingyu's blog #副标题description: “Talk is cheap. Show me the code.”————多说无益，看代码 #描述author: Summingyu #作者名（填你自己的）email: summingbest@gmail.comlanguage: zh-Hans #显示的语言timezone: Asia/Shanghai #时区avatar: /images/avatar.png #头像图片url: https://summingyu.github.io deploy: type: git #使用Git 发布 repo: https://github.com/username/username.github.io.git # 刚创建的Github仓库 主题配置主题配置在username.github.io/themes/next/_config.yml中修改链接 注意：如果启动后发现主题空白，注意看主题配置_config.yml的_internal字段，如果是_internal: vendors就改成_internal: lib查看作者原始解决方案 编写第一篇文章吧 手动创建文件在目录username.github.io/source/_posts下创建第一篇文章Hello,World.md 123456789101112----title: "Hello,World"date: 2016-11-17 11:42:00tags: - 学习 - 基础categories: - sed and awk 101 hacks---&gt; Hello,World!咪啪 使用命令创建可以使用hexo n &quot;Hello,World&quot;程序会自动在username.github.io/source/_posts目录下创建Hello,World.md文件，然后按照上面的编写就行了。 测试看看是否成功使用命令hexo s启动服务当出现 1INFO Hexo is running at http://localhost:4000/. Press Ctrl+C to stop. 说明已经启动成功了，可以用浏览器访问本地的127.0.0.1:4000查看结果了。如果部署在远程服务器，访问远程服务器的4000端口就行。 安装自动部署工具1npm install hexo-deployer-git --save 上传到github仓库以上全部完成，那么，可以上传本地文件到github仓库了1hexo clean &amp;&amp; hexo g &amp;&amp; hexo d 执行这个命令后，让你输入github的账户密码，输入完成后就可以在浏览器上访问https:/username.github.io.git了]]></content>
    </entry>

    
    <entry>
      <title><![CDATA[Chapter 13. Additional Awk Commands(附加命令)]]></title>
      <url>%2F2016%2F11%2F16%2FSed_and_Awk%2FChapter13%2F</url>
      <content type="text"><![CDATA[85. Pretty Printing Using printf(灵动输出使用printf)语法：1printf "print format", variable1, variable2, etc. 特殊符号 printf将不使用OFS,ORS的值使用了printf之后，OFS,ORS参数将失效1234567891011121314151617$ cat printf1.awkBEGIN &#123; FS=","; OFS=":"; ORS="\n--\n";&#125;&#123; printf "%s^^%s\n\n", $2, $3&#125;$ awk -f printf1.awk items.txtHD Camcorder^^VideoRefrigerator^^ApplianceMP3 Player^^AudioTennis Racket^^SportsLaser Printer^^Office 定制格式符 Print with Fixed Column Width (Basic)(输出固定列宽)同C一样，在%后面加上限定宽度，e.g. %05s 最少5个字符宽度，不足在前面补0 %5s 最少5个字符宽度，不足在前面补空格(右对齐) %-5s最少5个字符宽度，不足再后面补空格(左对齐) %.1s保留位数，浮点数是保留多少位小数Dot . Precision123456789101112131415161718192021222324252627$ cat dot.awkBEGIN &#123; print "----Using .1----" printf ".1d--&gt; %.1d\n", 101.23 printf ".1e--&gt; %.1e\n", 101.23 printf ".1f--&gt; %.1f\n", 101.23 printf ".1g--&gt; %.1g\n", 101.23 print "----Using .4----" printf ".4d--&gt; %.4d\n", 101.23 printf ".4e--&gt; %.4e\n", 101.23 printf ".4f--&gt; %.4f\n", 101.23 printf ".4g--&gt; %.4g\n", 101.23&#125;$ awk -f dot.awk----Using .1---.1d--&gt; 101.1e--&gt; 1.0e+02.1f--&gt; 101.2.1g--&gt; 1e+02----Using .4---.4d--&gt; 0101.4e--&gt; 1.0123e+02.4f--&gt; 101.2300.4g--&gt; 101.2 Print Report to File(输出结果到文件)同shell脚本一样，可以配合&gt; 、&gt;&gt;在awk脚本内或命令行添加输出到文件参数 86. Built-in Numeric Functions(内建数值函数)Awk int(n) Functionint函数，将值格式化为整数型 不是四舍五入，而是截断，print int(4.9)结果为4。 Awk log(n) Function$\log{n}$ Awk sqrt(n) Function(平方根函数)$\sqrt {n}$ Awk exp(n) Function(指数函数)形如$e^n$ Awk sin(n)、cos(n) Function$\sin(n)$ $\cos(n)$ Awk atan2(m,n) Function(反正切函数)$\arctan m/n$ 87. Random Number Generator(随机数生成器)Awk rand() Function(随机数函数)该函数随机生成一个0~1之间的一个数 Awk srand(n) Function(随机数初始化函数)种子函数seed种子不变，每次的随机数序列都是一样的。 88. Generic String Functions(典型字符串函数)Index Function(目录函数)可以查找特定字符在特定字符串的位置1234567891011121314$ cat index.awkBEGIN &#123; state="CA is California" print "String CA starts at location",index(state,"CA"); print "String Cali starts at location",index(state,"Cali"); if (index(state,"NY")==0) print "String NY is not found in:", state&#125;$ awk -f index.awkString CA starts at location 1String Cali starts at location 7String NY is not found in: CA is California Length Function(长度函数)输出特定字符串长度length(string) Split Function(分割函数)将特定字符串按分隔符分割写入输出数组语法1split(input-string,output-array,separator) 如果第三个参数没有指定，则使用默认的FS Substr Function(截取函数)将指定字符串从指定位置，输出指定长度的内容语法1substr(input-string, location, length) 12345678表示是从第3个字段里的第6个字符开始，一直到设定的分隔符","结束.awk -F ',' '&#123;print substr($3,6)&#125;'表示是从第3个字段里的第10个字符开始，截取8个字符结束.substr($3,10,8)表示是从第3个字段里的第6个字符开始，一直到结尾substr($3,6) 89. GAWK/NAWK String Functions(GAWK/NAWK特有字符串函数)Sub Function(替换函数)语法1sub(original-string,replacement-string,string-variable) 将指定字符串(string-variable)的源字符串(original-string)替换成替换字符串(replacement-string) 第三个参数是可选的，默认为$0当成功执行sub函数，返回的结果是1而不是0每行记录值替换最左边匹配到的字符串一次 Gsub Function(全局替换函数)用法和sub一样的相当于sed &#39;s///g&#39; Match Function () and RSTART, RLENGTH variables(match函数和RSTART,RLENGTH参数)查找指定字符串或正则表达式语法1match(input-string,search-string) 12345678910$ cat match.awkBEGIN &#123; state="CA is California" if (match(state,"Cali")) &#123; print substr(state,RSTART,RLENGTH),"is present in:", state; &#125;&#125;$ awk -f match.awkCali is present in: CA is California RSTART 匹配字符串在源字符串开始的位置 RLENGTH 匹配字符串长度90. GAWK String Functions(GAWK特有的字符串函数)改变大小写函数tolower和toupper函数是只在GAWK才有效的函数 91. Argument Processing (ARGC, ARGV, ARGIND)参数处理 在命令行上，参数ARGC和ARGV将会被忽略 ARGC是统计参数个数 ARGV是一个数组，里面记录了参数值，index从0开始到ARGC 当你有5个参数，则ARGC的值为6 ARGV[0]值总是awk ARGIND是当前处理文件的序列号ARGV[ARGIND]里面的值为当前处理的文件名 只有一个文件是ARGIND为192. OFMTThe OFMT built-in variable is available only in NAWK and GAWK.这个函数值只在NAWK和GAWK里有效.g是全局的，.f是指☞.后面的12345678910111213141516171819202122232425262728293031323334353637$ cat ofmt.awkBEGIN &#123; total=143.123456789; print "---using g----" print "Default OFMT:", total; OFMT="%.3g"; print "%.3g OFMT:", total; OFMT="%.4g"; print "%.4g OFMT:", total; OFMT="%.5g"; print "%.5g OFMT:", total; OFMT="%.6g"; print "%.6g OFMT:", total; print "---using f----" OFMT="%.0f"; print "%.0f OFMT:", total; OFMT="%.1f"; print "%.1f OFMT:", total; OFMT="%.2f"; print "%.2f OFMT:", total; OFMT="%.3f"; print "%.3f OFMT:", total;&#125;$ awk -f ofmt.awk---using g----Default OFMT: 143.123%.3g OFMT: 143%.4g OFMT: 143.1%.5g OFMT: 143.12%.6g OFMT: 143.123---using f---%.0f OFMT: 143%.1f OFMT: 143.1%.2f OFMT: 143.12%.3f OFMT: 143.123 93. GAWK Built-in Environment Variables(内建环境变量)只有GAWK有效 ENVIRON这个是非常有用的，当你想在awk脚本中调用shell的环境变量时。ENVIRON是一个数组，包含了所有环境变量的值的数组，而index的值则是环境变量的名字。For example,ENVIRON[&quot;PATH&quot;]表示的就是环境变量PATH的值 IGNORECASEIGNORECASE默认值为0，表示大小写敏感，可以设置为1表示忽略大小写 ERRNO错误输出，将错误信息写入到变量ERRNO中 94. Awk Profiler - pgawk这个选项会将程序文件以一种很优美的方式输出（译注：用于格式化 awk 脚本文件）。默认输出文件是 awkprof.out。先创建一个awk脚本1234567891011121314$ cat profiler.awkBEGIN &#123; FS=","; print "Report Generated On:" strftime("%a %b %d %H:%M: %S %Z %Y",systime());&#125;&#123; if ( $5 &lt;= 5 ) print "Buy More: Order", $2, "immediately!" else print "Sell More: Give discount on", $2, "immediately!"&#125;END &#123; print "----"&#125; 执行下面命令1$ pgawk --profile=myprofiler.out -f profiler.awk items.txt 查看输出的格式化脚本12345678910111213141516171819202122232425$ cat myprofiler.out # gawk 配置, 创建 Sun Sep 18 12:28:22 2016 # BEGIN 块 BEGIN &#123; 1 FS = "," 1 print ("Report Generated On:" (strftime("%a %b %d %H:%M: %S %Z %Y", systime()))) &#125; # 规则 3 &#123; 3 if ($5 &lt;= 5) &#123; # 3 3 print "Buy More: Order", $2, "immediately!" &#125; else &#123; print "Sell More: Give discount on", $2, "immediately!" &#125; &#125; # END 块 END &#123; 1 print "----" &#125; 发现进行了格式化 95. Bit Manipulation(位操作)与或非、左移、右移1234567891011121314151617$ cat bits.awkBEGIN &#123; number1=15 number2=25 print "AND: " and(number1,number2); print "OR: " or(number1,number2) print "XOR: " xor(number1,number2) print "LSHIFT: " lshift(number1,2) print "RSHIFT: " rshift(number1,2)&#125;$ awk -f bits.awkAND: 9OR: 31XOR: 22LSHIFT: 60RSHIFT: 3 96. User Defined Functions(用户自定义函数)语法：1234function fn-name(parameters)&#123; function-body&#125; 97. Language Independent Output (Internationalization)(语言独立输出(国际))98. Two Way CommunicationAwk can communication to an external process using “|&amp;”, which is two way communication.使用|&amp;标记能调用其他命令123456789101112$ cat two-way.awkBEGIN &#123; command = "sed 's/Awk/Sed and Awk/'" print "Awk is Great!" |&amp; command close(command,"to"); command |&amp; getline tmp print tmp; close(command);&#125;$ awk -f two-way.awkSed and Awk is Great! 99. System Function(system函数)你可以在system函数里调用外部内建函数123$ awk 'BEGIN &#123; system("date") &#125;'Mon Sep 19 09:49:37 CST 2016 100. Timestamp Functions(时间函数)These are available only in GAWK.systime() 101. getline Command(getline命令)单独使用getline 则读取下一行(和sed的n命令一样)123$ awk -F"," '&#123;getline; print $0;&#125;' items.txt 102,Refrigerator,Appliance,850,2104,Tennis Racket,Sports,190,20105,Laser Printer,Office,475,5 getline后面带参数和sed的hold空间差不多12345678$ awk -F"," '&#123;getline tmp; print "$0-&gt;", $0; print "tmp-&gt;", tmp;&#125;' items.txt$0-&gt; 101,HD Camcorder,Video,210,10tmp-&gt; 102,Refrigerator,Appliance,850,2$0-&gt; 103,MP3 Player,Audio,270,15tmp-&gt; 104,Tennis Racket,Sports,190,20$0-&gt; 105,Laser Printer,Office,475,5tmp-&gt; 104,Tennis Racket,Sports,190,20 读取一个文件使用&lt; 读取一个文件到变量1234567891011$ awk -F"," '&#123;print $0; getline tmp &lt; "items-sold.txt"; print tmp;&#125;' items.txt101,HD Camcorder,Video,210,10101 2 10 5 8 10 12102,Refrigerator,Appliance,850,2102 0 1 4 3 0 2103,MP3 Player,Audio,270,15103 10 6 11 20 5 13104,Tennis Racket,Sports,190,20104 2 3 4 0 6 5105,Laser Printer,Office,475,5105 10 2 5 7 12 6 读取一个外部命令12345678910111213141516171819202122$ cat getline1.awkBEGIN &#123; FS=","; "date" | getline close("date") print "Timestamp:" $0&#125;&#123; if ( $5 &lt;= 5 ) print "Buy More: Order", $2, "immediately!" else print "Sell More: Give discount on", $2, "immediately!"&#125;$ awk -f getline1.awk items.txtTimestamp:Sat Mar 5 09:29:22 PST 2011Sell More: Give discount on HD Camcorder immediately!Buy More: Order Refrigerator immediately!Sell More: Give discount on MP3 Player immediately!Sell More: Give discount on Tennis Racket immediately!Buy More: Order Laser Printer immediately!]]></content>
    </entry>

    
    <entry>
      <title><![CDATA[Chapter 12. Awk Associative Arrays（结合数组）]]></title>
      <url>%2F2016%2F11%2F16%2FSed_and_Awk%2FChapter12%2F</url>
      <content type="text"><![CDATA[77. Assigning Array Elements（赋值数组元素）语法：1arrayname[string]=value arrayname 数组的名字 string 数组的目录，下标 value 值数组的下标不一定要是序列，从0-10等，可以是字符串。可以相当于字典。和python差不多 78. Referring to Array Elements（引用数组元素）当定义了一个数组，即使里面没有值，也可以调用。因为系统赋值了空的值1234567awk 'BEGIN &#123;x=item[105];for (105 in item) print "yes";&#125;' yes 定义了item[105]，但是里面是没有值的，也能调用成功 79. Browse the Array using For Loop(使用循环浏览数组)语法1for (var in arrayname) actions 80. Delete Array Element(删除数组元素)语法1delete arrayname[index]; 也可以使用循环删除数组的所有元素In GAWK,可以使用delete arrayname删除数组所有元素 81. Multi Dimensional Array(多维数组)1234567891011121314151617$ cat array-multi3.awkBEGIN &#123; item["1,1"]=10; item["1,2"]=20; item[2,1]=30; item[2,2]=40; for (x in item) print "Index",x,"contains",item[x];&#125;$ awk -f array-multi3.awkIndex 1,1 contains 10Index 1,2 contains 20Index 2#1 contains 30Index 2#2 contains 40 下标使用&quot;&quot;时，里面的都算一个下标而没有分号，使用逗号,时，则为多维数组 82. SUBSEP - Subscript Separator(下标分隔符)下标分隔符默认为# 83. Sort Array Values using asort(使用asort排序数组的值)asort函数是将数组的值进行排序后，将下标用数字1-n表示123456789101112131415161718192021222324252627282930313233343536373839404142$ cat asort.awkBEGIN &#123; item[101]="HD Camcorder"; item[102]="Refrigerator"; item[103]="MP3 Player"; item[104]="Tennis Racket"; item[105]="Laser Printer"; item[1001]="Tennis Ball"; item[55]="Laptop"; item["na"]="Not Available"; print "------Before asort------" for (x in item) print "Index",x,"contains",item[x]; total = asort(item); print "------After asort------" for (x in item) print "Index",x,"contains",item[x]; print "Return value from asort:", total;&#125;$ awk -f asort.awk------Before asort-----Index 55 contains LaptopIndex 101 contains HD CamcorderIndex 102 contains RefrigeratorIndex 103 contains MP3 PlayerIndex 104 contains Tennis RacketIndex 105 contains Laser PrinterIndex na contains Not AvailableIndex 1001 contains Tennis Ball------After asort-----Index 4 contains MP3 PlayerIndex 5 contains Not AvailableIndex 6 contains RefrigeratorIndex 7 contains Tennis BallIndex 8 contains Tennis RacketIndex 1 contains HD CamcorderIndex 2 contains LaptopIndex 3 contains Laser PrinterReturn value from asort: 8 看到上面的例子，排序后输出并没有按顺序输出，这是因为for (x in item)输出是无序的，可以使用for (i=1; i&lt;= total; i++) 进行有序输出 asort不修改原值赋值下面的例子将不会修改原item数组，而会建立新的数组itemnew来排序1total = asort(item, itemnew); 84. Sort Array Indexes using asorti（使用asorti排序indexs的值）和asort用法一样，只不过是排序的对象不一样 注意如果你使用asorti(array)，那么原来array的值将会替换成排序后的indexs。所以小心使用，多使用asorti(array,arraynew)]]></content>
    </entry>

    
    <entry>
      <title><![CDATA[Chapter 11. Awk Conditional Statements and Loops（条件语句和循环）]]></title>
      <url>%2F2016%2F11%2F16%2FSed_and_Awk%2FChapter11%2F</url>
      <content type="text"><![CDATA[69. Simple If Statement（简单的if语句）Single Action （单个动作）语法12if (conditional-expression) action if是关键词 conditional-expression是判断语句 action为执行的动作 Multiple Actions（多个动作）语法12345if (conditional-expression)&#123; action1; action2;&#125; 实例12$ awk -F "," \ '&#123; if ( ($4 &gt;= 500 &amp;&amp; $4 &lt;= 1000) &amp;&amp; ($5 &lt;= 5)) \ print "Only",$5,"qty of",$2,"is available";&#125;' items.txtOnly 2 qty of Refrigerator is available 70. If Else Statement同C语言 一行非此即彼语法1conditional-expression ? action1 : action2 ; 71. While Loop(while循环)同C 72. Do-While Loop(do-while循环)同C 73. For Loop Statement（for循环）同C语法1for(initialization;condition;increment/decrement) actions 74. Break Statement(跳出语句)同C 75. Continue Statement(继续语句)同C 76. Exit Statement(退出语句)在函数内是退出函数，在脚本内是退出脚本退出时返回状态码0与Break语句比，跳出的更多]]></content>
    </entry>

    
    <entry>
      <title><![CDATA[Chapter 10. Awk Variables and Operators]]></title>
      <url>%2F2016%2F11%2F16%2FSed_and_Awk%2FChapter10%2F</url>
      <content type="text"><![CDATA[62. Variables(变量)关键字不能被使用为变量名。和其他的编程语言不同，你不需要声明变量才能使用它。如果你想初始化变量，最好在BEGIN块，它将只执行一次 实例创建一个文件1234567$ vi employee-sal.txt101,John Doe,CEO,10000102,Jason Smith,IT Manager,5000103,Raj Reddy,Sysadmin,4500104,Anand Ram,Developer,4500105,Jane Miller,Sales Manager,3000 编写一个awk脚本,统计薪水1234567891011$ cat total-company-salary.awkBEGIN &#123; FS=","; total=0;&#125;&#123; print $2 "'s salary is: " $4; total=total+$4&#125; END &#123; print "---\nTotal company salary = $"total;&#125; 12345678$ awk -f total-company-salary.awk employee-sal.txtJohn Doe's salary is: 10000Jason Smith's salary is: 5000Raj Reddy's salary is: 4500Anand Ram's salary is: 4500Jane Miller's salary is: 3000---Total company salary = $27000 63. Unary Operators（单元操作符）和数字前的正负号和C语言的自加自减符号一样遵循负负得正原则123456789101112131415161718192021222324$ vi negative.txt-1-2-3$ awk '&#123;print +$1&#125;' negative.txt-1-2-3$ awk '&#123;print -$1&#125;' negative.txt123awk '&#123;print ++$1&#125;' negative.txt 0-1-2awk '&#123;print $1++,$1&#125;' negative.txt -1 0-2 -1-3 -2 64. Arithmetic Operators(算数运算符) 65. String Operator(字符串运算符)空格`是字符串操作符，链接两个字符串string3=string1 string2` 66. Assignment Operators(赋值运算符)like C=、+=、-=、*=、/=、%= 67. Comparison Operators(对比运算符)like C&gt;、&gt;=、&lt;、&lt;=、!=、==、&amp;&amp;、|| 68. Regular Expression Operators(正则表达式运算符) ~ 匹配正则表达式 !~ 不匹配正则表达式(匹配不符合的)]]></content>
    </entry>

    
    <entry>
      <title><![CDATA[Chapter 9. Awk Built-in Variables（内建变量）]]></title>
      <url>%2F2016%2F11%2F16%2FSed_and_Awk%2FChapter9%2F</url>
      <content type="text"><![CDATA[55. FS - Input Field Separator(输入字段分隔符)默认的输入字段分隔符为空格space 可以使用awk选项-F设置 可以使用内建变量FS=&quot;&quot;在BEGIN块内设置1234567891011121314awk 'BEGIN &#123; FS=","; \ print "-------------\nName\tTitle\n-------------" &#125; \&#123; print $2,"\t",$3; &#125; \END &#123;print "-------------"&#125;' employee.txt-------------Name Title-------------John Doe CEOJason Smith IT Manager Raj Reddy Sysadmin anand Ram DeveloperJane Miller Sales Manager------------- 多分隔符当你文本里各个字段使用的分隔符不一样时，Don’t worry,你可以指定MULTIPLE多分隔符FS = &quot;[,:%]&quot;表示以,或:或%分隔 56. OFS - Output Field Separator(输出分隔符)FS是输入分隔符，对输入文件进行分隔。OFS是输出分隔符，对输出文件进行格式化输出。默认也是space空格输出是使用逗号，则默认使用OFS的默认值。没有使用逗号，则不使用12$ awk 'BEGIN &#123; print "test1","test2" &#125;'test1 test2 12$ awk 'BEGIN &#123; print "test1" "test2" &#125;'test1test2 Note:使用的是变量时，则不管有没有逗号，都默认有OFS123456awk -F, '/^102/ &#123;print $3 $2&#125;' employee.txt IT Manager Jason Smith---------------------------------------awk -F, '/^102/ &#123;print $3$2&#125;' employee.txt IT Manager Jason Smith 57. RS - Record Separator(记录分隔符)awk默认的一条记录是一行，而记录分隔符可以将多行看成一条记录处理，也可以将一行拆分成多个记录。 将一行差分成多个记录1234$ vi employee-one-line.txt101,John Doe:102,Jason Smith:103,Raj Reddy:104,AnandRam:105,Jane Miller 没有使用记录分隔符，则只会输出下面结果123$ awk -F, '&#123;print $2&#125;' employee-one-line.txtJohn Doe:102 以:分隔一行记录12345678$ awk -F, 'BEGIN &#123; RS=":" &#125; \&#123; print $2 &#125;' employee-one-line.txtJohn DoeJason SmithRaj ReddyAnand RamJane Miller 多行当作一条记录123456789101112131415161718192021$ vi employee-change-fs-ofs.txt101John DoeCEO-102Jason SmithIT Manager-103Raj ReddySysadmin-104Anand RamDeveloper-105Jane MillerSales Manager 以-\n为记录分隔符12345678$ awk 'BEGIN &#123; FS="\n"; RS="-\n"; OFS=":" &#125; \&#123;print $2, $3&#125;' employee-change-fs-ofs.txtJohn Doe:CEOJason Smith:IT ManagerRaj Reddy:SysadminAnand Ram:DeveloperJane Miller:Sales Manager 58. ORS - Output Record Separator（输出记录分隔符）同OFS相同，都是对输出进行格式化，差别是OFS是对字段间的分隔，而ORS是对记录的分隔12345678910111213$ awk 'BEGIN &#123; FS=","; ORS="\n---\n" &#125; \&#123;print $2, $3&#125;' employee.txtJohn Doe CEO---Jason Smith IT Manager---Raj Reddy Sysadmin---Anand Ram Developer---Jane Miller Sales Manager--- OFS为\n，ORS为\n---\n结果1234567891011121314151617181920212223$ awk 'BEGIN &#123; FS=","; OFS="\n";ORS="\n---\n" &#125; \&#123;print $1,$2,$3&#125;' employee.txt101John DoeCEO--102Jason SmithIT Manager--103Raj ReddySysadmin--104Anand RamDeveloper--105Jane MillerSales Manager--- 59. NR - Number of Records（记录条号）一条记录一个数字，表示第几条记录 Note：BEGIN块NR为0，END块NR为最后一条记录号12345678910awk 'BEGIN &#123;print NR&#125; \ &#123;print NR,$1&#125; \END &#123;print NR&#125;' employee.txt 01 101,John2 102,Jason3 103,Raj4 104,anand5 105,Jane5 59.5 NF - Number of Fields in a record（一条记录里的列数）60. FILENAME – Current File Name(获取当前文件的文件名)当我们后面没有添加输入文件时（比如用通道符|处理的输入流），则获取的FILENAME的值为- Note:当FILENAME在BEGIN块内时，则获取的值为””空。因为BEGIN块在输入流之前 61. FNR - File “Number of Record” 和NR的区别是FNR是表示当前输入文件的记录数，而NR是整个输入的记录数FNR在有多个输入文件时会每个文件重新计数，而NR不会]]></content>
    </entry>

    
    <entry>
      <title><![CDATA[Chapter 8. Awk Syntax and Basic Commands]]></title>
      <url>%2F2016%2F11%2F16%2FSed_and_Awk%2FChapter8%2F</url>
      <content type="text"><![CDATA[Awk是一个强大的处理文本的语言 AWK is original AWK. NAWK is new AWK. GAWK is GNU AWK.所有的Linux发行版本都自带GAWK在linux系统中，你可以看到/bin/awk是一个软链接，链接到/bin/gawk 创建简单的实验文件 employee.txtemployee-number,employee-name,employee-title 123456$ vi employee.txt101,John Doe,CEO102,Jason Smith,IT Manager103,Raj Reddy,Sysadmin104,Anand Ram,Developer105,Jane Miller,Sales Manager items.txtitem-number,item-description,item-category,cost,quantityavailable123456$ vi items.txt101,HD Camcorder,Video,210,10102,Refrigerator,Appliance,850,2103,MP3 Player,Audio,270,15104,Tennis Racket,Sports,190,20105,Laser Printer,Office,475,5 items-sold.txtitem-number qty-sold-month1 qty-sold-month2 qty-sold-month3 qty-sold-month4 qty-sold-month5 qty-sold-month6123456$ vi items-sold.txt101 2 10 5 8 10 12102 0 1 4 3 0 2103 10 6 11 20 5 13104 2 3 4 0 6 5105 10 2 5 7 12 6 51. Awk Command Syntax基本语法 awk -Fs ‘/pattern/ {action}’ input-file (or)awk -Fs ‘{action}’ intput-file /pattern/ {action}：表示当匹配到了/pattern/则执行{action} 52. Awk Program Structure (BEGIN, body, END block)Awk程序结构。一个典型的Awk命令有三个结构 BEGIN块 body块 END 块BEGIN block开始块语法：1BEGIN &#123; awk-commands &#125; BEGIN块只在程序运行之初执行一次，在输入文件所有行之前 BEGIN块是打印的报告头和初始化变量的好地方。 您可以在开始块有一个或一个以上的awk命令。 关键字BEGIN应该大写字母指定。 开始块是可选的。body block基本语法：1/pattern/ &#123;action&#125; 主体块讲在每行执行一次executed once for every line in the input file END Block基本语法：1END &#123; awk-commands &#125; 和BEGIN块一样，只在结尾执行一次 END块是打印报表页脚和做任何清理活动的好地方。 您可以在END块的一个或多个AWK命令。 关键字应该以大写字母指定。 END块是可选的。AWK处理流程图一个简单的AWK例子12345678$ awk 'BEGIN &#123; FS=":";print "---header---" &#125; \/mail/ &#123;print $1&#125; \END &#123; print "---footer---"&#125;' /etc/passwd---header--mailmailnull---footer--- 创建AWK脚本执行先穿件一个AWK脚本文件1234567891011$ vi myscript.awkBEGIN &#123; FS=":" print "---header---"&#125;/mail/ &#123; print $1&#125;END &#123; print "---footer---"&#125; 然后执行命令123456$ awk -f myscript.awk /etc/passwd---header--mailmailnull---footer--- 三个模块是都是可选的一般来说，BEGIN和END模块都是可选的，主要用body块但是，也有只用BEGIN块的123$ awk 'BEGIN &#123; print "Hello World!" &#125;'Hello World! Multiple Input Files多个输入文件直接在后面添加参数文件就行。 BEGIN块和END块都是只执行一次的，不管有多少个输入文件 53. Print Command（打印命令）默认情况，print命令将输出所有行，就和cat命令一样awk &#39;{print}&#39; employee.txt你也可以输出特定字段，默认分隔符为空格-F &#39; &#39;下列命令是等价的123awk -F ',' '&#123;print $2&#125;' employee.txtawk -F "," '&#123;print $2&#125;' employee.txtawk -F, '&#123;print $2&#125;' employee.txt 而$0等价与全部12awk '&#123;print&#125;' employee.txtawk '&#123;print $0&#125;' employee.txt 54. Pattern Matching（模式匹配）和sed命令差不多，匹配到相应行才执行后续命令1234567awk -F, '&#123;print $3,":is:",$2&#125;' employee.txt CEO :is: John DoeIT Manager :is: Jason SmithSysadmin :is: Raj ReddyDeveloper :is: anand RamSales Manager :is: Jane Miller 可以看出print还能在中间拼接文字，只有匹配到的行输出了123awk -F, '/^102/ &#123;print $3,":is:",$2&#125;' employee.txtIT Manager :is: Jason Smith]]></content>
    </entry>

    
    <entry>
      <title><![CDATA[Chapter 7. Sed Multi-Line Commands and loops]]></title>
      <url>%2F2016%2F11%2F16%2FSed_and_Awk%2FChapter7%2F</url>
      <content type="text"><![CDATA[sed多行命令和循环，默认情况下sed命令是单行处理 46. Append Next Line to Pattern Space (N command)添加下一行到P空间将回车替换成\n写入一行 在同一行输出行号1234567sed = employee.txt |sed '&#123;N;s/\n/ /g&#125;'1 101,John Doe,CEO2 102,Jason Smith,IT Manager 3 103,Raj Reddy,Sysadmin 4 104,anand Ram,Developer5 105,Jane Miller,Sales Manager n与N；2n与2N差异化研究####下面例子显示结果是在第2N遍执行sed-command里面的2N命令；在第N遍则不执行推论：如为3N则第3N遍执行.123456789sed -n '&#123;x;2N;s/\n/:/;p;G;s/\n/::/;p&#125;' employee.txt ::101,John Doe,CEO101,John Doe,CEO:103,Raj Reddy,Sysadmin 101,John Doe,CEO:103,Raj Reddy,Sysadmin ::102,Jason Smith,IT Manager 102,Jason Smith,IT Manager 102,Jason Smith,IT Manager ::104,anand Ram,Developer104,anand Ram,Developer104,anand Ram,Developer::105,Jane Miller,Sales Manager 而n参数是输出最后一行123456789sed -n '&#123;x;2n;s/\n/:/;p;G;s/\n/::/;p&#125;' employee.txt ::101,John Doe,CEO103,Raj Reddy,Sysadmin 103,Raj Reddy,Sysadmin ::102,Jason Smith,IT Manager 102,Jason Smith,IT Manager 102,Jason Smith,IT Manager ::104,anand Ram,Developer104,anand Ram,Developer104,anand Ram,Developer::105,Jane Miller,Sales Manager 步骤分析 47. Print 1st Line in MultiLine (P command)输出多行的第一行。P命令为输出模式空间，直到遇到一个\n符号，所以如果模式空间里有多个\n换行符（比如有个N命令），则只输出第一行。 48. Delete 1st Line in MultiLine (D command)删除多行的第一行 49. Loop and Branch (b command and :label)循环和分支b命令打上标签label，然后:label为锚点，跳到指定标签位:label处执行 50. Loop Using t command循环使用t命令1234567891011121314151617$ vi label-t.sed #!/bin/sed -nf h;n;H;x s/\n/:/ :repeat/Manager/ s/^/*/ /\*\*\*/!t repeat p$ chmod u+x label-t.sed$ ./label-t.sed empnametitle.txt John Doe:CEO***Jason Smith:IT Manager Raj Reddy:Sysadmin Anand Ram:Developer***Jane Miller:Sales Manager 下面一小段代码是循环的 123 :repeat/Manager/ s/^/*//\*\*\*/!t repeat :repeat ：这个是标签 /Manager/ s/^/*/： 匹配Manager行，在行首加一个*号 /\*\*\*/!t repeat ：判断如果上一句执行成功，并且不是***则跳到标签repeat继续执行]]></content>
    </entry>

    
    <entry>
      <title><![CDATA[Chapter 6. Sed Hold and Pattern Space Commands]]></title>
      <url>%2F2016%2F11%2F16%2FSed_and_Awk%2FChapter6%2F</url>
      <content type="text"><![CDATA[sed的保留空间和模式空间 pattern space（模式空间）相当于车间sed把流内容在这里处理； hold space（保留空间）相当于仓库，加工的半成品在这里临时储存（当然加工完的成品也在这里存储）。 41. Swap Pattern Space with Hold Space (x command)交换H空间和P空间里面的内容1234567891011121314151617181920212223[root@localordb sed_test]# sed -e 'x;n' empnametitle.txt CEOJohn DoeIT ManagerJason SmithSysadminRaj ReddyDeveloperAnand RamSales Manager[root@localordb sed_test]# cat empnametitle.txt John DoeCEOJason SmithIT ManagerRaj ReddySysadminAnand RamDeveloperJane MillerSales Manager sed ‘x;N’ employee.txt 步骤分析123456# sed 'x;n' employee.txt 102,Jason Smith,IT Manager 101,John Doe,CEO104,anand Ram,Developer103,Raj Reddy,Sysadmin 42. Copy Pattern Space to Hold Space (h command)拷贝P空间到H空间 Print the names of the managers(输出managers的名字)123# sed -n -e '/Manager/!h' -e '/Manager/&#123;x;p&#125;' empnametitle.txtJason SmithJane Miller /Manager/!h 不匹配Manager的行拷贝到H空间 /Manager/{x;p} 匹配到Manager后，交换H空间的内容，并输出 43. Append Pattern Space to Hold Space (H command)添加P空间到H空间 44. Copy Hold Space to Pattern Space (g command)get从H空间复制到P空间 45. Append Hold Space to Pattern Space (G command)添加P空间到H空间]]></content>
    </entry>

    
    <entry>
      <title><![CDATA[Chapter 5. Additional Sed Commands(扩展的sed命令)]]></title>
      <url>%2F2016%2F11%2F16%2FSed_and_Awk%2FChapter5%2F</url>
      <content type="text"><![CDATA[28. Append Line After (a command)你可以使用a命令在匹配到行后面添加新行 Syntax(语法)1$ sed '[address] a the-line-to-append' input-file Add a new record(记录)to the employee.txt file after line number:对employee.txt文件在指定行号后面添加一个新的记录1234567$ sed '2 a 203,Jack Johnson,Engineer' employee.txt 101,John Doe,CEO102,Jason Smith,IT Manager 203,Jack Johnson,Engineer 103,Raj Reddy,Sysadmin 104,Anand Ram,Developer105,Jane Miller,Sales Manager 29. Insert Line Before (i command)使用i命令在匹配到行前面插入新行 Syntax(语法)1$ sed '[address] i the-line-to-insert' input-file 30. Change Line (c command)使用c命令，修改匹配到的行 Syntax(语法)1$ sed '[address] c the-line-to-insert' input-file 31. Combine a, i, and c Commands(联合使用a,i,c命令)12345678910111213$ sed '/Jason/ &#123; a\204,Jack Johnson,Engineer i\202,Mark Smith,Sales Engineer c\203,Joe Mason,Sysadmin&#125;' employee.txt 101,John Doe,CEO202,Mark Smith,Sales Engineer 203,Joe Mason,Sysadmin 204,Jack Johnson,Engineer 103,Raj Reddy,Sysadmin 104,Anand Ram,Developer105,Jane Miller,Sales Manager 32. Print Hidden Characters (l command)(显示隐藏字符)例如\t tab字符，$行尾1234$ cat tabfile.txt fname First Name lname Last Namemname Middle Name 执行l命令显示tab和EOL1234$ sed -n l tabfile.txt fname\tFirst Name$ lname\tLast Name$mname\tMiddle Name$ 当你在l命令后面指定一个数字n，则在匹配行的第n个字符处打印一个\ This works only on GNU sed.12345678910$ sed -n 'l 20' employee.txt101,John Doe,CEO$102,Jason Smith,IT \Manager$103,Raj Reddy,Sysad\min$104,Anand Ram,Devel\oper$105,Jane Miller,Sal\es Manager$ 33. Print Line Numbers (= command)打印行号 Print all line numbers123456$ sed = employee.txt 1101,John Doe,CEO 2102,Jason Smith,IT Manager 3103,Raj Reddy,Sysadmin 4104,Anand Ram,Developer 5105,Jane Miller,Sales Manager Print line numbers only for lines 1,2 and 3:1234567$ sed '1,3 =' employee.txt 1101,John Doe,CEO2102,Jason Smith,IT Manager3103,Raj Reddy,Sysadmin 104,Anand Ram,Developer105,Jane Miller,Sales Manager 34. Change Case (using the y ‘transform’ command)一对一替换，感觉用处不大。加密用？ In this example character “a” will be transformed to A, b to B, c to C, etc.:123456$ sed 'y/abcde/ABCDE/' employee.txt 101,John DoE,CEO102,JAson Smith,IT MAnAgEr 103,RAj REDDy,SysADmin 104,AnAnD RAm,DEvElopEr105,JAnE MillEr,SAlEs MAnAgEr 35. Multiple Files in Command Line可以在一行命令行下对多个文件使用同一个sed123$ sed -n '/root/ p' /etc/passwd /etc/grouproot:x:0:0:root:/root:/bin/bashroot:x:0: 36. Quit Sed (q command)q命令是第一次匹配到行后退出 Note:q命令对地址范围是无效的。因为匹配到第一行的时候就退出了 37. Read from File (r command)读取文件，并将文本内容输出到标准输出12345678910[root@localordb sed_test]# sed '1 r log.txt' employee.txt 101,John Doe,CEO1.717 2.6011.771 26.1511.789 20.0021.789 25.130102,Jason Smith,IT Manager 103,Raj Reddy,Sysadmin 104,anand Ram,Developer105,Jane Miller,Sales Manager 38. Simulating Unix commands in sed (cat, grep, head)用sed模仿其他命令 39. Sed Command Line Options-n option静默模式，禁止默认的输出You can also use --quiet, or –-silent instead of -n. They are identical in function.我们也可以使用--quiet, or –-silent代替-n -f option(--file option)读取sed脚本 -e option(--expression option)执行一个sed命令 -i option(-ibak等价于--in-place=bak)替换选项，重写输入文件 -c option(和-i选项联合使用)和-i联合使用，-ibak是备份原文件，加-c选项则是新建一个bak文件，将-i替换的文件写入新建文件。源文件不变你也可以使用--copy选项。等价与-c -l option(--line-length option)指定行长度进行分割 40. Print Pattern Space (n command)注意，不是-n选项读取下一行，并打印模式空间里的内容123456789101112sed '&#123;&gt; =&gt; n&gt; &#125;' employee.txt1101,John Doe,CEO102,Jason Smith,IT Manager 3103,Raj Reddy,Sysadmin 104,anand Ram,Developer5]]></content>
    </entry>

    
    <entry>
      <title><![CDATA[Chapter 4. Sed Execution(执行)]]></title>
      <url>%2F2016%2F11%2F16%2FSed_and_Awk%2FChapter4%2F</url>
      <content type="text"><![CDATA[23. Multiple Sed Commands in Command Line在命令行上多个sed命令 1. Use multiple -e option in the command line使用多个-e选项1sed -e 'command1' -e 'command2' -e 'command3' Search for root, or nobody, or mail in the /etc/passwd file:1sed -n -e '/^root/ p' -e '/^nobody/ p' -e '/^mail/ p' /etc/passwd 2. Break-up several sed commands using \使用\分割多个sed命令当你有一个非常长的命令时，你可以使用\换行分割多个选项1234sed -n -e '/^root/ p' \ -e '/^nobody/ p' \ -e '/^mail/ p' \/etc/passwd 3. Group multiple commands using { }当你有一个大量的sed 选项时，你可以使用{}12345sed -n '&#123; /^root/ p /^nobody/ p /^mail/ p&#125;' /etc/passwd tips:-e选项后面每个选项都用&#39;&#39;分割，{}里面每一行一个选项，不用&#39;&#39;分割 24. Sed Script Files(sed脚本文件)如果你想去重复使用一套sed命令时，你可以创建一个sed脚本文件，每一行一个sed选项，使用-f参数调用文件123$ vi mycommands.sed s/\([^,]*\),\([^,]*\),\(.*\).*/\2,\1,\3/g s/^.*/&lt;&amp;&gt;/s/Developer/IT Manager/s/Manager/Director/ 123456$ sed -f mycommands.sed employee.txt &lt;John Doe,101,CEO&gt;&lt;Jason Smith,102,IT Director&gt; &lt;Raj Reddy,103,Sysadmin&gt; &lt;Anand Ram,104,IT Director&gt;&lt;Jane Miller,105,Sales Director&gt; 25. Sed Comments(sed注释)我们知道sed使用晦涩难懂的语言，可能这次知道怎么什么意思，下次就忘了，所以可以使用注释行，帮助快速回忆123456789$ vi mycommands.sed # Swap field 1 (employee id) with field 2 (employee name)s/\([^,]*\),\([^,]*\),\(.*\).*/\2,\1,\3/g # Enclose the whole line within &lt; and &gt; s/^.*/&lt;&amp;&gt;/# Replace Developer with IT Manager s/Developer/IT Manager/ # Replace Manager with Directors/Manager/Director/ Note: If the 1st 2 characters of the 1st line in the*.sed script are#n, sed will automatically use the-n (don’t print the pattern buffer)option.如果*.sed脚本第一行的前两个字符时#n，则sed将自动使用-n参数(不打印缓冲区模式) 26. Sed as an Interpretersed作为一种编译器和shell脚本一样，可以在sed脚本第一行添加编译环境#!/bin/sed -f使bash识别为sed脚本。12345678910$ vi myscript.sed #!/bin/sed -f# Swap field 1 (employee id) with field 2 (employee name)s/\([^,]*\),\([^,]*\),\(.*\).*/\2,\1,\3/g # Enclose the whole line within &lt; and &gt; s/^.*/&lt;&amp;&gt;/# Replace Developer with IT Managers/Developer/IT Manager/ # Replace Manager with Directors/Manager/Director/ 现在，给sed脚本执行权限,并执行123chmod u+x myscript.sed ./myscript.sed employee.txt 你也可以在第一行后面使用-n 参数1234$ vi testscript.sed #!/bin/sed -nf /root/ p/nobody/ p 不是-fn参数 27. Modifying the Input File Directly（直接修改输入文件）使用-i参数，直接修改输入文件 Replace John with Johnny in the original employee.txt file itself:12345678$ sed -i 's/John/Johnny/' employee.txt $ cat employee.txt 101,Johnny Doe,CEO102,Jason Smith,IT Manager 103,Raj Reddy,Sysadmin 104,Anand Ram,Developer105,Jane Miller,Sales Manager 你可以直接使用-i参数修改输入文件，但是要异常小心。这时候，你可以在-i参数后面添加命名，在写入新内容之前创建一个原始文件的备份 Replace John with Johnny in the original employee.txt file but save a backup copy:1$ sed -ibak 's/John/Johnny/' employee.txt 已经将原始文件备份为employee.txtbak123456$ cat employee.txtbak 101,John Doe,CEO102,Jason Smith,IT Manager 103,Raj Reddy,Sysadmin 104,Anand Ram,Developer105,Jane Miller,Sales Manager 而原始文件已经修改了123456$ cat employee.txt 101,Johnny Doe,CEO102,Jason Smith,IT Manager 103,Raj Reddy,Sysadmin 104,Anand Ram,Developer105,Jane Miller,Sales Manager 你也可以使用长的-i参数--in-place.下面两个命令是等价的12sed -ibak 's/John/Johnny/' employee.txt sed --in-place=bak 's/John/Johnny/' employee.txt]]></content>
    </entry>

    
    <entry>
      <title><![CDATA[Chapter 3. Regular Expressions（正则表达式）]]></title>
      <url>%2F2016%2F11%2F16%2FSed_and_Awk%2FChapter3%2F</url>
      <content type="text"><![CDATA[Chapter 3. Regular Expressions（正则表达式）20. Regular Expression Fundamentals（正则表达式基础） Beginning of line (^ ) End of line ( $) Single Character (.) Zero or more Occurrences (*) One or more Occurrence (\+) Zero or one Occurrence (\?) Escaping the Special Character (\) Character Class ([0-9]) 21. Additional Regular Expressions （扩展正则表达式） OR Operation (|) Exactly M Occurrences ({m}) M to N Occurrences ({m,n}) Word Boundary (\b)（单词边界符） Back References (\n)（反向引用，n为数字）22. Sed Substitution Using Regular ExpressionConvert the DOS file format to Unix file format using sed:使用sed将DOS下的新行换行符(CR/LF)替换成Unix下的格式1sed 's/.$//' filename]]></content>
    </entry>

    
    <entry>
      <title><![CDATA[Chapter2 Sed Substitute 代替 Command]]></title>
      <url>%2F2016%2F11%2F16%2FSed_and_Awk%2FChapter2%2F</url>
      <content type="text"><![CDATA[Chapter 2. Sed Substitute（代替） Command6. Sed Substitute Command Syntax123sed '[address-range|pattern-range] s/originalstring/replacement-string/[substitute-flags]' inputfile#sed '[地址范围|模板范围] s/原始字符串/替换字符串/[替换flag]' 输入文件 地址范围或者模板范围是可选的。如果你没有选择这个选项, sed将会在所有行执行替换命令 s – 告诉sed执行替换命令 original-string –原始字符串将会在输入文件中搜寻。 原始字符串也能够是正则表达式 replacement-string – Sed 将会用这个字符串替换原始字符串 substitute-flags是可选的。 它可以包含以下一个或者多个值 源文件不会被修改 Replace all occurrences of Manager with Director:123456$ sed 's/Manager/Director/' employee.txt 101,John Doe,CEO 102,Jason Smith,IT Director103,Raj Reddy,Sysadmin104,Anand Ram,Developer 105,Jane Miller,Sales Director Replace Manager with Director only on lines that contain the keyword ‘Sales’:根据关键字行替换。只在匹配到关键字的行替换123456$ sed '/Sales/s/Manager/Director/' employee.txt 101,John Doe,CEO102,Jason Smith,IT Manager 103,Raj Reddy,Sysadmin 104,Anand Ram,Developer105,Jane Miller,Sales Director 7. Global Flag (g flag)全局flag：sed默认替换模式是只替换每一行第一个匹配到的原始字符串。如果你需要替换每一个字符串，则需要加上全局标志：g flag Note：因为没有指定范围，所以这些实例将应用到整个文件中。 8. Number Flag (1,2,3.. flag)使用数字Flag，将指定替换匹配到的每行的特定第n个原始字符串。Counting starts over on each line, and n can be anything from 1 to 512.从每行开始计数到结束，n能够取1-512范围（实测，到4096也没问题，之后没测。估计旧版本是到512）12sed 's/2/3/4096' 1|grep -o 3 3 Note: 如果单行没有指定多个匹配字符串，则这行nothing is changed 9. Print Flag (p flag)p flag输出替换成功的行。和大部分p参数一样，联合-n参数一起使用，禁止默认输出所有行 Print only the line that was changed by the substitute command:1$ sed -n 's/John/Johnny/p' employee.txt 101,Johnny Doe,CEO 1234567[root@localordb 1]# sed -n 's/7/3/p' 1 3777[root@localordb 1]# sed 's/7/3/p' 1 1637773777 10. Write Flag (w flag)将替换成功的行写入文件。等价于p参数+重定向&gt;(不是&gt;&gt;)。大多数人都是使用p输出再重定向到文件。所以这个参数不常用。而且不能输出到源文件 11. Ignore Case Flag (i flag)忽略大小写。匹配时忽略原字符串的大小写。 12. Execute Flag (e flag)执行命令flag，你可以执行任何一个有效的shell命令，将匹配到的源字符串当作命令参数，并输出结果。只有GNU的sed命令支持e flag123$ cat files.txt /etc/passwd/etc/group 123$ sed 's/^/ls -l /e' files.txt -rw-r--r-- 1 root root 1547 Oct 27 08:11 /etc/passwd-rw-r--r-- 1 root root 651 Oct 27 08:11 /etc/group 13. Combine Sed Substitution Flags你可以将多个Flag组合使用 14. Sed Substitution Delimiter你可以更改定界符。如果替换字符串中有/，再使用/定界符时要加转义字符\，这样很丑，而且不易读所以sed支持使用其他符号作为定界符，以达到易读的效果。12$ sed 's/\/usr\/local\/bin/\/usr\/bin/' path.txt reading /usr/bin directory 1234sed 's|/usr/local/bin|/usr/bin|' path.txt sed 's^/usr/local/bin^/usr/bin^' path.txt sed 's@/usr/local/bin@/usr/bin@' path.txtsed 's!/usr/local/bin!/usr/bin!' path.txt 15. Multiple Substitute Commands Affecting the Same Linesed命令可以对同一行执行多个sed替换命令执行命令1之后，再执行命令2，知道执行完成，读取下一行。 Change Developer to IT Manager, then change Manager to Director:12345678910$ sed '&#123;&gt; s/Developer/IT Manager/ &gt; s/Manager/Director/ &gt; &#125;' employee.txt 101,John Doe,CEO 102,Jason Smith,IT Director 103,Raj Reddy,Sysadmin 104,Anand Ram,IT Director105,Jane Miller,Sales Director 可以看到，第四行执行了两次替换命令 1.Read:1104,Anand Ram,Developer 2. Execute:先执行了第一个替换命令s/Developer/IT Manager/1104,Anand Ram,IT Manager 然后执行了第二个替换命令s/Manager/Director/1104,Anand Ram,IT Director Remember:第二个命令是在第一个命令执行完成的基础上执行的 3. Print:执行完成所有的命令之后，输出结果1104,Anand Ram,IT Director 4. Repeat:读取下一行，接着从step #1执行 更换两个命令顺序，结果不同123456789101112131415161718sed '&#123; &gt; s/Manager/Director/&gt; s/Developer/IT Manager/ &gt; &#125;' employee.txt101,John Doe,CEO102,Jason Smith,IT Director103,Raj Reddy,Sysadmin104,Anand Ram,IT Manager105,Jane Miller,Sales Director#############################cat employee.txt 101,John Doe,CEO102,Jason Smith,IT Manager103,Raj Reddy,Sysadmin104,Anand Ram,Developer105,Jane Miller,Sales Manager 16. Power of &amp; - Get Matched Pattern当&amp;被使用在替换字符串中时，它将匹配任何源字符串或者正则表达式。这是非常强大并实用的 ###1234567$ sed 's/^[0-9][0-9][0-9]/[&amp;]/g' employee.txt[101],John Doe,CEO[102],Jason Smith,IT Manager[103],Raj Reddy,Sysadmin[104],Anand Ram,Developer[105],Jane Miller,Sales Manager 17. Substitution Grouping (Single Group)使用\(和\)来确定分组，然后使用反向引用(e.g.\1 - \9)来引用分组 Single grouping:1234567$ sed 's/\([^,]*\).*/\1/g' employee.txt101102103104105 encloses the 1st letter in every word inside (), if the 1st character is upper case.123# echo "The Geek Stuff Hello world" | sed 's/\(\b[A-Z]\)/\(\1\)/g'(T)he (G)eek (S)tuff (H)ello world 18. Substitution Grouping (Multiple Group)替换正则里有多个()的捕获分组，则可以用\1 - \9来反向引用 19. Gnu Sed Only Replacement String Flags这些Flags只在GNU版本的sed命令才有效。这些Flags命令能用在替换字符串部分 \l ,\L,\u,\Ureplacement string flag替换大小写，不管你替换字符串后面是大写还是小写，同意换成对应Flag的样式 \l为flag之后一个字符串为小写 \L为flag之后所有字符串全为小写 \u为flag之后一个字符串为大写 \U为flag之后所有字符串全为大写12345$ sed -n 's/John/JO\lHNNY/p' employee.txt 101,JOhNNY Doe,CEO#========================#$ sed -n 's/John/JO\LHNNY/p' employee.txt 101,JOhnny Doe,CEO \E replacement string flag这个替换flag是联合\U,\L使用的，表示大小写替换的结束处1234567Change John to JOHNNY BOY: $ sed -n 's/John/\UJohnny Boy/p' employee.txt 101,JOHNNY BOY Doe,CEO#=========================#Change John to JOHNNY Boy:$ sed -n 's/John/\UJohnny\E Boy/p' employee.txt101,JOHNNY Boy Doe,CEO Replacement String Flag UsagesEmployee name in all upper case, and title in all lower case:1234567$ sed 's/\([^,]*\),\([^,]*\),\(.*\).*/\U\2\E,\1,\L\3/g' employee.txt JOHN DOE,101,ceoJASON SMITH,102,it manager RAJ REDDY,103,sysadmin ANAND RAM,104,developerJANE MILLER,105,sales manager]]></content>
    </entry>

    
    <entry>
      <title><![CDATA[Chapter 1: Sed Syntax and Basic Commands]]></title>
      <url>%2F2016%2F11%2F16%2FSed_and_Awk%2FChapter1%2F</url>
      <content type="text"><![CDATA[Chapter 1: Sed Syntax and Basic Commandssed examples使用的sed 案例均为下面文件123456$ vi employee.txt101,John Doe,CEO102,Jason Smith,IT Manager103,Raj Reddy,Sysadmin104,Anand Ram,Developer105,Jane Miller,Sales Manager 1. Sed Command Syntaxsed基本语法1sed [options] &#123;sed-commands&#125; &#123;input-file&#125; sed读取文本为按行读取匹配 输出/etc/passwd文件的所有行1234567891011sed -n 'p' /etc/passwd[root@localhost ~]# sed -n 'p' /etc/passwdroot:x:0:0:root:/root:/bin/bashbin:x:1:1:bin:/bin:/sbin/nologindaemon:x:2:2:daemon:/sbin:/sbin/nologinadm:x:3:4:adm:/var/adm:/sbin/nologinlp:x:4:7:lp:/var/spool/lpd:/sbin/nologinsync:x:5:0:sync:/sbin:/bin/syncshutdown:x:6:0:shutdown:/sbin:/sbin/shutdownhalt:x:7:0:halt:/sbin:/sbin/halt sed命令文件的基本语法1sed [options] -f &#123;sed-commands-in-a-file&#125; &#123;input-file&#125; sed命令文件格式为一行一个sed命令，实现多个sed命令123456[root@localhost SedAwk]# cat test-script.sed /^root/ p/^nobody/ p[root@localhost SedAwk]# sed -n -f test-script.sed /etc/passwdroot:x:0:0:root:/root:/bin/bashnobody:x:99:99:Nobody:/:/sbin/nologin sed使用-e参数实现多个sed命令1sed [options] -e &#123;sed-command-1&#125; -e &#123;sed-command-2&#125; &#123;input-file&#125; 123[root@localhost SedAwk]# sed -n -e '/^root/ p' -e '/^nobody/ p' /etc/passwdroot:x:0:0:root:/root:/bin/bashnobody:x:99:99:Nobody:/:/sbin/nologin 为了方便阅读，可以使用\换行1234sed -n \-e '/^root/ p' \-e '/^nobody/ p' \/etc/passwd 也可以使用{}包括命令组1234sed [options] '&#123;sed-command-1sed-command-2&#125;' input-file 例如：123456[root@localhost SedAwk]# sed -n '&#123;&gt; /^root/ p&gt; /^nobody/ p&gt; &#125;' /etc/passwdroot:x:0:0:root:/root:/bin/bashnobody:x:99:99:Nobody:/:/sbin/nologin 2.Sed Scripting FlowSed命令运行步骤 Read 逐行读取 Execute 逐行执行命令 one by one Print 可以是空匹配 Repeat 重复步骤 3. Print Pattern Space (p command)Using the sed p command, you can print the current pattern space.使用p命令，你可以输出当前的模式 The following example prints every line of employee.txt twice:单独使用p命令会使每行都输出两次123456789101112$ sed 'p' employee.txt101,John Doe,CEO101,John Doe,CEO102,Jason Smith,IT Manager102,Jason Smith,IT Manager103,Raj Reddy,Sysadmin13Sed and Awk 101 Hacks103,Raj Reddy,Sysadmin104,Anand Ram,Developer104,Anand Ram,Developer105,Jane Miller,Sales Manager105,Jane Miller,Sales Manager Print each line once (functionally the same as ‘cat employee.txt’):配合n命令可以只输出一次 -n 取消默认的输出123456$ sed -n 'p' employee.txt101,John Doe,CEO102,Jason Smith,IT Manager103,Raj Reddy,Sysadmin104,Anand Ram,Developer105,Jane Miller,Sales Manager Specifying an Address Range 指定地址范围如果你不指定范围，sed默认匹配全部行 Print only the 2nd line:12$ sed -n '2 p' employee.txt102,Jason Smith,IT Manager Print from line 1 through line 4:123456$ sed -n '1,4 p' employee.txt101,John Doe,CEO102,Jason Smith,IT Manager103,Raj Reddy,Sysadmin104,Anand Ram,Developer14Sed and Awk 101 Hacks Print from line 2 through the last line ($ represents the last line):输出第二行一直到最后一行$匹配最后一行12345$ sed -n '2,$ p' employee.txt102,Jason Smith,IT Manager103,Raj Reddy,Sysadmin104,Anand Ram,Developer105,Jane Miller,Sales Manager Modify Address Range三种模式：逗号模式，加号模式，和波浪号模式 逗号模式 表示绝对的地址范围 加号模式 表示相对的地址范围 波浪号模式 表示等差序列的步长1234• 1~2 matches 1,3,5,7, etc.• 2~2 matches 2,4,6,8, etc.• 1~3 matches 1,4,7,10, etc.• 2~3 matches 2,5,8,11, etc. Print only odd numbered lines:输出奇数行1234$ sed -n '1~2 p' employee.txt101,John Doe,CEO103,Raj Reddy,Sysadmin105,Jane Miller,Sales Manager Pattern Matching 模板匹配Print lines matching the pattern “Jane”:12$ sed -n '/Jane/ p' employee.txt105,Jane Miller,Sales Manager Print lines starting from the 1st match of “Jason” until the 4th line:输出从第一个Jason行开始到第四行的所有行(并且输出所有的匹配到Jason的行)1234$ sed -n '/Jason/,4 p' employee.txt102,Jason Smith,IT Manager103,Raj Reddy,Sysadmin104,Anand Ram,Developer Note: If there were no matches for “Jason” in the 1st 4 lines, thiscommand would print the lines that match “Jason” after the 4th line. 如果在前四行没有匹配到Jason，则在第四行之后只输出匹配到Jason的行 Print lines starting from the 1st match of “Raj” until the last line:1234$ sed -n '/Raj/,$ p' employee.txt103,Raj Reddy,Sysadmin104,Anand Ram,Developer105,Jane Miller,Sales Manager Print lines starting from the 1st line matching “Raj” until the 1st line matching “Jane”:1234$ sed -n '/Raj/,/Jane/ p' employee.txt103,Raj Reddy,Sysadmin104,Anand Ram,Developer105,Jane Miller,Sales Manager 如果Raj匹配行后没有找到Jane匹配行，则输出到最后行。（不管前面是否有Jane行，都不会输出Jane行）该模式会循环匹配（Jane之后还有Raj到Jane也会输出，只有Raj会输出后面所有行）12345678910111213st=&gt;start: startop=&gt;operation: read a lineop1=&gt;operation: printop2=&gt;operation: skipop3=&gt;operation: read a lineop4=&gt;operation: printcond=&gt;condition: Raj yes or no?cond1=&gt;condition: Jane yes or no?ed=&gt;endst-&gt;op-&gt;cond(yes)-&gt;op1-&gt;op3-&gt;cond1(no)-&gt;op1cond(no)-&gt;op2-&gt;opcond1(yes)-&gt;op4-&gt;op Print the line matching “Jason” and 2 lines immediately after that:1234$ sed -n '/Jason/,+2 p' employee.txt102,Jason Smith,IT Manager103,Raj Reddy,Sysadmin104,Anand Ram,Developer 4. Delete Lines (d command)使用d参数，可以删除行。 NOTE:d参数仅仅只删除输出流，就像其他的sed参数，并不会修改原始文件。如果不使用其他参数，单独使用d参数，则匹配所有行，所以不会有任何输出。 相当于p参数的非，不显示匹配到的行。如果前面使用-n参数，则不会有任何输出因为d参数没有输出功能，-n参数是取消默认输入的输出1sed 'd' employee.txt Useful Delete Examples (常用实例)删除空行:1sed '/^$/ d' employee.txt 删除所有注释行:1sed '/^#/ d' employee.txt NOTE:当使用多个命令参数匹配同一行时，d命令执行之后会删除匹配行，不会在删除行进一步执行后续命令12345[root@localhost SedAwk]# sed -n -e '2 d' -e '2 p' employee.txt [root@localhost SedAwk]# sed -n -e '2 p' -e '2 d' employee.txt102,Jason Smith,IT Manager[root@localhost SedAwk]# 5. Write Pattern Space to File (w command)将标准输出输入到指定文件 Write the content of employee.txt file to file output.txt (and display on screen):1234567891011121314$ sed 'w output.txt' employee.txt101,John Doe,CEO102,Jason Smith,IT Manager19Sed and Awk 101 Hacks103,Raj Reddy,Sysadmin104,Anand Ram,Developer105,Jane Miller,Sales Manager$ cat output.txt101,John Doe,CEO102,Jason Smith,IT Manager103,Raj Reddy,Sysadmin104,Anand Ram,Developer105,Jane Miller,Sales Manager Write the content of employee.txt file to output.txt file but not to screen:加-n参数，将不会输出标准输入 使用w参数会覆盖原本文件里面的内容12345678$ sed -n 'w output.txt' employee.txt$ cat output.txt101,John Doe,CEO102,Jason Smith,IT Manager103,Raj Reddy,Sysadmin104,Anand Ram,Developer105,Jane Miller,Sales Manager Write only the 2nd line:1234$ sed -n '2 w output.txt' employee.txt$ cat output.txt102,Jason Smith,IT Manager Note: You might not use the w command frequently. Most people useUNIX output redirection, instead, to store the output of sed to a file.For example: sed &#39;p&#39; employee.txt &gt; output.txt你可能不会使用w命令，因为大部分在UNIX系统中，使用&gt;符号代替]]></content>
    </entry>

    
  
  
</search>
