shell小技巧(五)把以abc开头的下一行以def结尾的两行替换成douyu

这个有点麻烦,需要关联上下行的两个条件。

方法1:

大致思路如下:

按行读取文件,存入数组。

以循环方式按顺序处理数组中的数据。

循环内判断行是否已abc开头,如果是则将变量存入临时变量,并不做输出处理;如果不是abc开头则直接输出变量内容到文件,进入下次循环

再次循环时,判断上一行是否是abc开头,如果是再判断本次的变量结尾是否是def。

如果条件不满足则先输出上一次循环变量(在临时变量内。)到文件,在输出本次循环的变量,临时变量清空,进入下次循环

如果条件满足,则输出duoyu字串到文件两行。

代码如下:

#!/bin/bash
f1=2
f2=""
f3=""
f4=""
while read line 
   do
     echo $line
     if [ $f1 -eq 1 ]; then
        #preline header include abc
        f1=2
        f3=${line: -3}
       f3=${f3}x
       f4=""
        if [ $f3 == "defx" ]; then
          #line tail include def
           echo "duoyu\n" >> s3.txt
           echo "duoyu\n" >> s3.txt
        else
           echo $f2 >> s3.txt
           echo $line >> s3.txt
        fi
     else
       f4=${line:0:3}
       f4=x$f4
       if [ $f4 == "xabc" ]; then
          f2=$line
          f1=1
       else
          echo $line >>s3.txt
       fi
     fi
   done < s1.txt
echo $line
if [ $f1 -eq 1 ]; then
   echo $f2 >> s3.txt
   f2=""
   f1=2
fi
代码简略说明:

 f4=${line:0:3}
       f4=x$f4

变量f4用于判断头部是否是abc,这里给头部加了一个字母x,为了避免刚好取得的3个字符是纯数字。

变量f3也是类似的思路。

-------------------------------------------------------

上面的代码理由漏洞。

第一个漏洞是对文件输入文件s1.txt和输出王文建s3.txt未做相应处理。

应该在头部先判断s1存在和不存在,并做处理。

对s3.txt直接清空即可。

第二个漏洞是在判断上一个循环变量头部包含abc,本次循环变量未包含def的情况,应对本次循环进行是否头部包含abc的检测,并做处理。

#!/bin/bash
> s3.txt
if [ -f s1.txt ]; then
   echo "starting..."
else
   echo "error!need s1.txt!"
   exit 1
fi

f1=2
f2=""
f3=""
f4=""
while read line 
   do
     echo $line
     if [ $f1 -eq 1 ]; then
        #preline header include abc
        f1=2
        f3=${line: -3}
       f3=${f3}x
       f4=""
        if [ $f3 == "defx" ]; then
          #line tail include def
           echo "duoyu\n" >> s3.txt
           echo "duoyu\n" >> s3.txt
        else
           echo $f2 >> s3.txt
           f4=${line:0:3}
           f4=x$f4
           if [ $f4 == "xabc" ]; then
              f2=$line
              f1=1
           else
              echo $line >>s3.txt
           fi

        fi
     else
       f4=${line:0:3}
       f4=x$f4
       if [ $f4 == "xabc" ]; then
          f2=$line
          f1=1
       else
          echo $line >>s3.txt
       fi
     fi
   done < s1.txt
echo $line
if [ $f1 -eq 1 ]; then
   echo $f2 >> s3.txt
   f2=""
   f1=2
fi

------------------------------

最后做点优化,有一部分代码是重复的,因此稍作调整可以避免重复代码。但是还要增加一个continue

#!/bin/bash
> s3.txt
if [ -f s1.txt ]; then
   echo "starting..."
else
   echo "error!need s1.txt!"
   exit 1
fi
f1=2
f2=""
f3=""
f4=""
while read line 
   do
     echo $line
     if [ $f1 -eq 1 ]; then
        #preline header include abc
        f1=2
        f3=${line: -3}
       f3=${f3}x
       f4=""
        if [ $f3 == "defx" ]; then
          #line tail include def
           echo "duoyu\n" >> s3.txt
           echo "duoyu\n" >> s3.txt
           continue;
        else
           echo $f2 >> s3.txt
        fi 
     fi
       f4=${line:0:3}
       f4=x$f4
       if [ $f4 == "xabc" ]; then
          f2=$line
          f1=1
       else
          echo $line >>s3.txt
       fi 

 done < s1.txt
echo $line
if [ $f1 -eq 1 ]; then
   echo $f2 >> s3.txt
   f2=""
   f1=2
fi

方法2:

这个用sed直接实现,方法来自某度

sed '/^abc/{N;/def$/s/.*/douyu/}' s1.txt

方法1方法2相比方法2比较简洁但是存在瑕疵。如果文件出现如下格式,方法二识别不出来。

abc8888888
abceeeeeeedef

即一行既满足头部abc,也满足尾部def的情况方法2无法识别。

你可能感兴趣的:(Shell技巧)