zoukankan      html  css  js  c++  java
  • linux 文本处理 三大剑客之一 ----sed

    sed命令简介

    sed处理时,有2个缓冲区:【pattern space】和【hold space】

    sed执行过程:

    先读入一行,去掉尾部换行符,存入【pattern space】,执行编辑命令。

    处理完毕,除非加了-n参数,把现在的【pattern space】打印出来,在后边打印曾去掉的换行符。

    把【pattern space】置空。 接着读下一行,处理下一行。

    sed的默认输出:【pattern space】里的内容输出到标准输出。

    sed的常用选项:

    • 【pattern space】里的内容不输出到标准输出:-n

    • 默认只能执行一个脚本,执行多个脚本:-e script, --expression=script

      可以有多个-e script

    • 如果要执行的脚本特别多,可以指定一个脚本文件:-f /path/to/sed_scirpt

      脚本文件里,每行一个编辑命令。

    • 支持使用扩展的正则表达式,默认是基本正则表达式:-r

    • 直接编辑原文件:-i

    • 把【pattern space】空间中的内容覆盖到【hold space】空间:h

    • 把【pattern space】空间中的内容追加到【hold space】空间,然后删除【pattern space】空间中的内容:H

    • 把【hold space】空间中的内容覆盖到【pattern space】空间:g

    • 把【hold space】空间中的内容追加到【pattern space】空间,然后删除【hold space】空间中的内容:G

    • 互换【hold space】【pattern space】里的内容:x

    • 把匹配到的行的下一行放入【pattern space】,并把匹配到的行删除掉:n

    • 把匹配到的行的下一行放入【pattern space】,不删除匹配到的行:N

    • 删除【pattern space】空间中的行:d

    • 删除多行模式下【pattern space】里的所有行。(比如用N了,【pattern space】里就有多行):D

    编辑命令:

    如果有多个命令,则用分号分隔。

    删掉【pattern space】里的内容:d

    删除start.sh的第二行到第六行。

    # nl start.sh | sed '2,6d' 
    1	#!/bin/sh
    7	-Dglobal.config.path=/home/htga/docker/docker/trunk/target/docker & -Xms256m -Xmx512m -classpath 
    8	/home/htga/docker/docker/trunk/target/docker/docker.jar com.hitotek.docker.DockerApplication 1000  
    9	 > /dev/null 2>&1 &)
    10	/dev/null 2>&1
    11	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED -Dglobal.config.path=$basepath -Xms256m -Xmx512m -classpath $basepath/docker.jar com.hitotek.docker.DockerApplication 1000 > /dev/null 2>&1 &)
    12	java -Dio.netty.leakDetectionLevel=ADVANCED 
    13	-Dglobal.config.path=/home/htga/docker/docker/trunk/target/docker -Xms256m -Xmx512m -classpath 
    14	/home/htga/docker/docker/trunk/target/docker/docker.jar 
    15	com.hitotek.docker.DockerApplication 1000  &)
    16	/dev/null
    
    在行前插入:-i ext 支持使用 实现多行插入
    # nl start.sh | sed '3i 
    ew line
    other line'
    
    1	#!/bin/sh
    2	set -xv
    3	basepath="$( cd "$(dirname "$0")"&& pwd )"
    new line
    other line
    4	echo $basepath
    5	$(nohup java )
    6	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED 
    7	-Dglobal.config.path=/home/htga/docker/docker/trunk/target/docker & -Xms256m -Xmx512m -classpath 
    8	/home/htga/docker/docker/trunk/target/docker/docker.jar com.hitotek.docker.DockerApplication 1000  
    9	 > /dev/null 2>&1 &)
    10	/dev/null 2>&1
    11	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED -Dglobal.config.path=$basepath -Xms256m -Xmx512m -classpath $basepath/docker.jar com.hitotek.docker.DockerApplication 1000 > /dev/null 2>&1 &)
    12	java -Dio.netty.leakDetectionLevel=ADVANCED 
    13	-Dglobal.config.path=/home/htga/docker/docker/trunk/target/docker -Xms256m -Xmx512m -classpath 
    14	/home/htga/docker/docker/trunk/target/docker/docker.jar 
    15	com.hitotek.docker.DockerApplication 1000  &)
    16	/dev/null
    
    在行后插入:-a ext 支持使用 实现多行插入
    # nl start.sh | sed '3i 
    ew line
    other line'
    
    1	#!/bin/sh
    2	set -xv
    new line
    other line
    3	basepath="$( cd "$(dirname "$0")"&& pwd )"
    4	echo $basepath
    5	$(nohup java )
    6	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED 
    7	-Dglobal.config.path=/home/htga/docker/docker/trunk/target/docker & -Xms256m -Xmx512m -classpath 
    8	/home/htga/docker/docker/trunk/target/docker/docker.jar com.hitotek.docker.DockerApplication 1000  
    9	 > /dev/null 2>&1 &)
    10	/dev/null 2>&1
    11	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED -Dglobal.config.path=$basepath -Xms256m -Xmx512m -classpath $basepath/docker.jar com.hitotek.docker.DockerApplication 1000 > /dev/null 2>&1 &)
    12	java -Dio.netty.leakDetectionLevel=ADVANCED 
    13	-Dglobal.config.path=/home/htga/docker/docker/trunk/target/docker -Xms256m -Xmx512m -classpath 
    14	/home/htga/docker/docker/trunk/target/docker/docker.jar 
    15	com.hitotek.docker.DockerApplication 1000  &)
    16	/dev/null
    
    替换行:-c ext 把匹配到的行,替换成text
    # nl start.sh | sed '/java/c #java被修改的'
    
    1	#!/bin/sh
    2	set -xv
    3	basepath="$( cd "$(dirname "$0")"&& pwd )"
    4	echo $basepath
    #java被修改的
    #java被修改的
    7	-Dglobal.config.path=/home/htga/docker/docker/trunk/target/docker & -Xms256m -Xmx512m -classpath 
    8	/home/htga/docker/docker/trunk/target/docker/docker.jar com.hitotek.docker.DockerApplication 1000  
    9	 > /dev/null 2>&1 &)
    10	/dev/null 2>&1
    #java被修改的
    #java被修改的
    13	-Dglobal.config.path=/home/htga/docker/docker/trunk/target/docker -Xms256m -Xmx512m -classpath 
    14	/home/htga/docker/docker/trunk/target/docker/docker.jar 
    15	com.hitotek.docker.DockerApplication 1000  &)
    16	/dev/null
    
    

    保存匹配到的行,到指定文件中:-w ./sedw.txt

    把带Java的行,保持到/tmp/fsnew

    # nl start.sh | sed -n '/java/w ./sedw.txt' 
    
    [root@localhost testsed]# ls
    sedw.txt  start.sh  testSed.sh  test.txt
    [root@localhost testsed]# cat sedw.txt 
    5	$(nohup java )
    6	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED 
    11	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED -Dglobal.config.path=$basepath -Xms256m -Xmx512m -classpath $basepath/docker.jar com.hitotek.docker.DockerApplication 1000 > /dev/null 2>&1 &)
    12	java -Dio.netty.leakDetectionLevel=ADVANCED 
    

    在匹配到的行的上一行,加上行号:=

    在以java的行的上一行加上行号

    # nl start.sh | sed '/java/=' 
    
    [root@localhost testsed]#  nl start.sh | sed '/java/='
         1	#!/bin/sh
         2	set -xv
         3	basepath="$( cd "$(dirname "$0")"&& pwd )"
         4	echo $basepath
    5
         5	$(nohup java )
    6
         6	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED 
         7	-Dglobal.config.path=/home/htga/docker/docker/trunk/target/docker & -Xms256m -Xmx512m -classpath 
         8	/home/htga/docker/docker/trunk/target/docker/docker.jar com.hitotek.docker.DockerApplication 1000  
         9	 > /dev/null 2>&1 &)
        10	/dev/null 2>&1
    11
        11	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED -Dglobal.config.path=$basepath -Xms256m -Xmx512m -classpath $basepath/docker.jar com.hitotek.docker.DockerApplication 1000 > /dev/null 2>&1 &)
    12
        12	java -Dio.netty.leakDetectionLevel=ADVANCED 
        13	-Dglobal.config.path=/home/htga/docker/docker/trunk/target/docker -Xms256m -Xmx512m -classpath 
        14	/home/htga/docker/docker/trunk/target/docker/docker.jar 
        15	com.hitotek.docker.DockerApplication 1000  &)
        16	/dev/null
    

    匹配到的行不执行后面的命令;没匹配到的行执行后面的命令:!。注意:!处理命令之前。

    删除不以#开头的行:

    # nl start.sh | sed '/^#/!d' /etc/fstab
    #
    [root@localhost testsed]# nl start.sh | sed '/java/!d'
         5	$(nohup java )
         6	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED 
        11	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED -Dglobal.config.path=$basepath -Xms256m -Xmx512m -classpath $basepath/docker.jar com.hitotek.docker.DockerApplication 1000 > /dev/null 2>&1 &)
        12	java -Dio.netty.leakDetectionLevel=ADVANCED 
    
    
    查找替换:s/要替换的/替换成的/替换标记。它的分隔符/可以自己指定,常用的有s@@@,s###

    替换标记:

    • 全局替换:g
    • 将替换成功的结果保存到文件:w /path/to/save
    • 显示替换成功的行:p

    练习

    1,删除test文件中所有以空白字符开头的行的行首的所有空白字符

    #  nl start.sh | sed 's@^[[:space:]]+@@'
    
    1	#!/bin/sh
    2	set -xv
    3	basepath="$( cd "$(dirname "$0")"&& pwd )"
    4	echo $basepath
    5	$(nohup java )
    6	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED 
    7	-Dglobal.config.path=/home/htga/docker/docker/trunk/target/docker & -Xms256m -Xmx512m -classpath 
    8	/home/htga/docker/docker/trunk/target/docker/docker.jar com.hitotek.docker.DockerApplication 1000  
    9	 > /dev/null 2>&1 &)
    10	/dev/null 2>&1
    11	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED -Dglobal.config.path=$basepath -Xms256m -Xmx512m -classpath $basepath/docker.jar com.hitotek.docker.DockerApplication 1000 > /dev/null 2>&1 &)
    12	java -Dio.netty.leakDetectionLevel=ADVANCED 
    13	-Dglobal.config.path=/home/htga/docker/docker/trunk/target/docker -Xms256m -Xmx512m -classpath 
    14	/home/htga/docker/docker/trunk/target/docker/docker.jar 
    15	com.hitotek.docker.DockerApplication 1000  &)
    16	/dev/null
    

    2,删除包含java的行 和 config 的行

    #  nl start.sh | sed -e 's@java@@' -e '/config/d'
         1	#!/bin/sh
         2	set -xv
         3	basepath="$( cd "$(dirname "$0")"&& pwd )"
         4	echo $basepath
         5	$(nohup  )
         6	$(nohup  -Dio.netty.leakDetectionLevel=ADVANCED 
         8	/home/htga/docker/docker/trunk/target/docker/docker.jar com.hitotek.docker.DockerApplication 1000  
         9	 > /dev/null 2>&1 &)
        10	/dev/null 2>&1
        12	 -Dio.netty.leakDetectionLevel=ADVANCED 
        14	/home/htga/docker/docker/trunk/target/docker/docker.jar 
        15	com.hitotek.docker.DockerApplication 1000  &)
        16	/dev/null
    

    sed的常用查询方式

    1、不给地址:对全文进行处理

    • nl start.sh |sed 'p'
    1	#!/bin/sh
    1	#!/bin/sh
    2	set -xv
    2	set -xv
    3	basepath="$( cd "$(dirname "$0")"&& pwd )"
    3	basepath="$( cd "$(dirname "$0")"&& pwd )"
    4	echo $basepath
    4	echo $basepath
    5	$(nohup java )
    5	$(nohup java )
    6	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED 
    6	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED 
    7	-Dglobal.config.path=/home/htga/docker/docker/trunk/target/docker & -Xms256m -Xmx512m -classpath 
    7	-Dglobal.config.path=/home/htga/docker/docker/trunk/target/docker & -Xms256m -Xmx512m -classpath 
    8	/home/htga/docker/docker/trunk/target/docker/docker.jar com.hitotek.docker.DockerApplication 1000  
    8	/home/htga/docker/docker/trunk/target/docker/docker.jar com.hitotek.docker.DockerApplication 1000  
    9	 > /dev/null 2>&1 &)
    9	 > /dev/null 2>&1 &)
    10	/dev/null 2>&1
    10	/dev/null 2>&1
    11	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED -Dglobal.config.path=$basepath -Xms256m -Xmx512m -classpath $basepath/docker.jar com.hitotek.docker.DockerApplication 1000 > /dev/null 2>&1 &)
    11	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED -Dglobal.config.path=$basepath -Xms256m -Xmx512m -classpath $basepath/docker.jar com.hitotek.docker.DockerApplication 1000 > /dev/null 2>&1 &)
    12	java -Dio.netty.leakDetectionLevel=ADVANCED 
    12	java -Dio.netty.leakDetectionLevel=ADVANCED 
    13	-Dglobal.config.path=/home/htga/docker/docker/trunk/target/docker -Xms256m -Xmx512m -classpath 
    13	-Dglobal.config.path=/home/htga/docker/docker/trunk/target/docker -Xms256m -Xmx512m -classpath 
    14	/home/htga/docker/docker/trunk/target/docker/docker.jar 
    14	/home/htga/docker/docker/trunk/target/docker/docker.jar 
    15	com.hitotek.docker.DockerApplication 1000  &)
    15	com.hitotek.docker.DockerApplication 1000  &)
    16	/dev/null
    16	/dev/null
    
    
    • nl start.sh |sed -n 'p'
    1	#!/bin/sh
    2	set -xv
    3	basepath="$( cd "$(dirname "$0")"&& pwd )"
    4	echo $basepath
    5	$(nohup java )
    6	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED 
    7	-Dglobal.config.path=/home/htga/docker/docker/trunk/target/docker & -Xms256m -Xmx512m -classpath 
    8	/home/htga/docker/docker/trunk/target/docker/docker.jar com.hitotek.docker.DockerApplication 1000  
    9	 > /dev/null 2>&1 &)
    10	/dev/null 2>&1
    11	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED -Dglobal.config.path=$basepath -Xms256m -Xmx512m -classpath $basepath/docker.jar com.hitotek.docker.DockerApplication 1000 > /dev/null 2>&1 &)
    12	java -Dio.netty.leakDetectionLevel=ADVANCED 
    13	-Dglobal.config.path=/home/htga/docker/docker/trunk/target/docker -Xms256m -Xmx512m -classpath 
    14	/home/htga/docker/docker/trunk/target/docker/docker.jar 
    15	com.hitotek.docker.DockerApplication 1000  &)
    16	/dev/null 
    

    2、单地址

    • #:指定行
    nl start.sh |sed -n '1p'  
    输出匹配的第一行
    1	#!/bin/sh
    
    
    • /pattern/:被此模式所匹配到的每一行
     nl start.sh |sed -n '/java/p'
    输出匹配的java的行
    5	$(nohup java )
    6	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED 
    11	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED -Dglobal.config.path=$basepath -Xms256m -Xmx512m -classpath $basepath/docker.jar com.hitotek.docker.DockerApplication 1000 > /dev/null 2>&1 &)
    12	java -Dio.netty.leakDetectionLevel=ADVANCED 
    
    

    3,地址范围

    • $:最后一行
    nl start.sh |sed -n '$p'
    16	/dev/null
    
    • #,#:起始和结束
    nl start.sh |sed -n '3','5p'     或者   nl start.sh |sed -n '3','5'p
    3	basepath="$( cd "$(dirname "$0")"&& pwd )"
    4	echo $basepath
    5	$(nohup java )
    
    • #,+#:起始,和从起始加多少行
    nl start.sh |sed -n '3','+5p'     或者   nl start.sh |sed -n '3','+5'p
    3	basepath="$( cd "$(dirname "$0")"&& pwd )"
    4	echo $basepath
    5	$(nohup java )
    6	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED 
    7	-Dglobal.config.path=/home/htga/docker/docker/trunk/target/docker & -Xms256m -Xmx512m -classpath 
    8	/home/htga/docker/docker/trunk/target/docker/docker.jar com.hitotek.docker.DockerApplication 1000  
    
    • #,/pat1/:起始到,pat1匹配到的行
    nl start.sh |sed -n '3','/docker/p'     或者   nl start.sh |sed -n '3','/docker/'p
    
    3	basepath="$( cd "$(dirname "$0")"&& pwd )"
    4	echo $basepath
    5	$(nohup java )
    6	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED 
    7	-Dglobal.config.path=/home/htga/docker/docker/trunk/target/docker & -Xms256m -Xmx512m -classpath 
    
    
    • /pat1/,/pat2/:pat1匹配到的行,到pat2匹配到的行
    nl start.sh |sed -n '/nohup/','/ADVANCED/'p     或者   nl start.sh |sed -n '3','/ADVANCED/'p
    5	$(nohup java )
    6	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED 
    11	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED -Dglobal.config.path=$basepath -Xms256m -Xmx512m -classpath $basepath/docker.jar com.hitotek.docker.DockerApplication 1000 > /dev/null 2>&1 &)
    12	java -Dio.netty.leakDetectionLevel=ADVANCED 
    

    4,步进:a~b

    a为初始值 b为 步数

    • 1~2:1,3,5,7,9.。。行(所有奇数行)
    nl start.sh |sed -n '1~2'p  
    
    1	#!/bin/sh
    3	basepath="$( cd "$(dirname "$0")"&& pwd )"
    5	$(nohup java )
    7	-Dglobal.config.path=/home/htga/docker/docker/trunk/target/docker & -Xms256m -Xmx512m -classpath 
    9	 > /dev/null 2>&1 &)
    11	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED -Dglobal.config.path=$basepath -Xms256m -Xmx512m -classpath $basepath/docker.jar com.hitotek.docker.DockerApplication 1000 > /dev/null 2>&1 &)
    13	-Dglobal.config.path=/home/htga/docker/docker/trunk/target/docker -Xms256m -Xmx512m -classpath 
    15	com.hitotek.docker.DockerApplication 1000  &)
    
    
    • 2~2:2,4,6,8,10.。。行(所有偶数行)
    nl start.sh |sed -n '2~2'p 
    2	set -xv
    4	echo $basepath
    6	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED 
    8	/home/htga/docker/docker/trunk/target/docker/docker.jar com.hitotek.docker.DockerApplication 1000  
    10	/dev/null 2>&1
    12	java -Dio.netty.leakDetectionLevel=ADVANCED 
    14	/home/htga/docker/docker/trunk/target/docker/docker.jar 
    16	/dev/null
    

    sed比较复杂的例子

    + 取出最后一行:

    # nl start.sh | sed '$!d'  或  nl start.sh | sed -n '$p'
    
    [root@localhost testsed]# nl start.sh | sed '$!d'
        16	/dev/null
    [root@localhost testsed]#  nl start.sh | sed -n '$p'
        16	/dev/null
    
    • 第一种解释:
    1. 1-15行不是最后一行 ($ 最后一行 ) 执行到 $ 条件不满足
    2. !条件不满足的时候 反而要执行
    3. 执行d (删除 pattern space 输出 pattern space时为空)
    4. 16行 执行到 $ 条件满足
    5. !条件满足的时候 不执行
    6. 不执行d
    7. 输出 pattern space 即 16行
    • 第二种的解释
    1. 1-15行不是最后一行 ($ 最后一行 ) 执行到 $ 条件不满足
    2. 条件不满足的时候 不执行p 即 pattern space 有1-15行数据
    3. 16行 执行到 $ 条件满足
    4. 条件满足的时候 执行p 输出 16行数据
    5. -n 参数 不输出 pattern space 即 16行

    显示奇数行:

    # nl start.sh | sed -n 'p;n'   或者 nl start.sh | sed -n '1~2p'
         1	#!/bin/sh
         3	basepath="$( cd "$(dirname "$0")"&& pwd )"
         5	$(nohup java )
         7	-Dglobal.config.path=/home/htga/docker/docker/trunk/target/docker & -Xms256m -Xmx512m -classpath 
         9	 > /dev/null 2>&1 &)
        11	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED -Dglobal.config.path=$basepath -Xms256m -Xmx512m -classpath $basepath/docker.jar com.hitotek.docker.DockerApplication 1000 > /dev/null 2>&1 &)
        13	-Dglobal.config.path=/home/htga/docker/docker/trunk/target/docker -Xms256m -Xmx512m -classpath 
        15	com.hitotek.docker.DockerApplication 1000  &)
    
    1. p: pattern space 这行 复制到 hold space

    2. n:把要操作的行 往下一行 ;

    执行流程解释

    读入第一行 pattern space

    执行p 把第一行的数据 直接输出

    执行n 把第二行的【pattern space】数据删除 读入第三行的数据到 pattern space

    没有 -n 再次输出第一行

    执行p 把第三行的数据 直接输出

    执行n 把第四行的【pattern space】数据删除 读入第五行的数据到 pattern space

    没有 -n 再次输出第三行

    执行p 把第五行的数据 直接输出

    执行n 把第六行的【pattern space】数据删除 读入第七行的数据到 pattern space

    没有 -n 再次输出第五行

    ………………

    执行p 把第十五行的数据 直接输出

    执行n 把第十六行的【pattern space】数据删除

    复杂查询特定连续几行:

    cat start.sh |
    	sed /^#/d |   
    	sed -n '/nohup/{
        p;
        /.*&.*/b endPo;
        :a;
        n;
        p;
        /.*&.*/!b a;
        :endPo;
        }' |  
    	sed -n '/nohup.*/{
    	/\/!b endPo;p;
    	:a;n;
    	p;
    	/\/b a;
    	:endPo;
    	}'
    
    • -n 只会输出匹配的行
    • ^特定开头
    • d 删除
    • p输出
    • b 跳跃某个节点
    • :a 指定a 节点
    • n 读下一行,并删除当前【pattern space】里的内容后,再把下一行的内容放入【pattern space】

    其他相关例子

     1,显示偶数行:
     nl start.sh | sed -n 'n;p'
     2,倒置文本:
     nl start.sh | sed '1!G;h;$!d' 
     
     nl start.sh | sed 'G'
    

    graph LR
    A["[]矩形"]-->|"-->箭头"|B("()圆角")
    B---|"---连线"|C(("双(())圆形"))
    C>|粗线|D{"{}菱形"}
    C-->E>">]为非对称"]

  • 相关阅读:
    夺命雷公狗—玩转SEO---50---让页面更好的被搜索引擎发现,自动推送篇
    夺命雷公狗—玩转SEO---49---让页面更好的被搜索引擎发现,主动推送篇
    夺命雷公狗—玩转SEO---48---让页面更好的被搜索引擎发现,外链篇
    夺命雷公狗—玩转SEO---47---让页面更好的被搜索引擎发现,网站地图篇
    夺命雷公狗—玩转SEO---46---浅谈搜索引擎
    夺命雷公狗—玩转SEO---45---浅入批量获得高频词
    夺命雷公狗—玩转SEO---44---外链群发原理
    夺命雷公狗—玩转SEO---43---外链提升网站权重
    夺命雷公狗—玩转SEO---42---快速交换友情链接
    夺命雷公狗—玩转SEO---41---H1标签的玩法
  • 原文地址:https://www.cnblogs.com/dongshanxia/p/13288458.html
Copyright © 2011-2022 走看看