sed note

sed的if-else条件处理

sed -n '/bsp/!p' file
sed -n '/bsp/!d' file

!号不是修饰p而是修饰前面的匹配模式的xxx,可以这么理解吗?, 忽略大小写的I选项也同理

cat work.txt |\
sed -n '/tag_a/,/tag_b/{
p;
/tag_b/a
}' #打印tag_a到tag_b之间的内容,并在tag_b之后加入一个空行,支持有多个这种段落
cat work.txt |\
sed -n '/tag_a/,/tag_b/!{
p;

}' -e '/tag_b/a'#打印除了tag_a到tag_b之间的内容,即提出tag_a到tag_b直接的内容,支持有多个这种段落

t是条件跳转,如果匹配成功则跳转到a,if(true)-else,T则是匹配失败则跳转,if(false)-else

sed "/ccc/s/$/\tYES/;ta;s/$/\tNO/;:a" test.txt

如果table在前面,可以实现循环

b是无条件跳转到a,同goto

sed "/ccc/s/$/\tYES/;ba;s/$/\tNO/;:a" test.txt

sed -n "/ccc/ \
    {
        s/$/\tYES/;
        a\new line
        p;
    };
    t end;
    s/$/\tNO/p;
    :end" \
    test.txt

sed -n "/ccc/I\
    {
        s/$/\tYES/
        p
        b end;
    }
    {
        s/$/\tNO/p
    }
    :end" \
    test.txt

sed -n "/ccc/ \
    {
        s/$/\tYES/;     #实现行尾追加,同理实现行首添加???
        a\new line
        p;
    };
    bend;               #强制跳转,相当于此句和目标tag之间的命令没有
    s/$/\tNO/p;
    :end" \
    test.txt



sed "/abc/ \
    {
        s/$/\ttrue/;
        b end;
    }
    s/$/\tfalse/;
    :end
    " ${file}
#匹配成功的行后添加\ttrue,匹配失败的行后添加\tfalse,即:首行的模式匹配后的{}是整体执行的。



sed "/abc/ \
    s/$/\ttrue/;
    b end;
    s/$/\tfalse/;
    :end
    " ${file}
#只会在匹配成功的行后面添加\ttrue,匹配失败的行没有行为,即:b end这一句是独立的,每次都执行。

满足条件后,多操作同时处理

sed -n "/^tcp/I{        #匹配以"tcp"开头的行,不区分大小写
        !d;             #不删除,即是删除其它行
        /.*[-]$/d;      #以"-"结束的行删除
        p;
    }" \
    test.txt
    
sed -n "/./{
        /^tcp/I!d;      #以"tcp"开头的行不删除
        /.*[-]$/d;      #以"-"结束的行删除
        p;
    }" \
    test.txt 

sed -e "aaa" -e "bbb"

sed -n -e '/id="23"/{s/isopen="1"/isopen="0"/p;}' -e '/id="24"/{s/isopen="1"/isopen="0"/p;};' datafile

等价于

sed -n '
    /id="23"/{s/isopen="1"/isopen="0"/p;};
    /id="24"/{s/isopen="1"/isopen="0"/p;};
' datafile

sed中使用shell命令

sed "s/^/$(echo $R%ANDOM).rmvb_/g"
sed "s/^/$(date +"%Y%m%d").rmvb_/g"

添加行

CONTENT="111
222
333
444
555"
echo "${CONTENT}" | sed -e "/222/{  \
a\aaa\r\nbbb
q;
}"

sed -i '/原行内容/a要添加的新一行内容' 文件
sed -i '25a/usr/local/php.ini' aaa.txt          #要在第25行插入一行新的内容 /usr/local/php.ini
sed -i '/I love apple/aDo you love it' aaa.txt  #在特定内容后插入一行

删除包含"My"的行到包含"You"的行之间的行(包括My行和You行)

sed '/My/,/You/d' datafile

行首的某些特殊字符有时候需要添加转义符,比如#和$

用#做分隔符,#为第一个字符时要转义

sed 's#/home/test/task/#abc/#g'
sed '\#/home/test/bin/aa.sh#d'

utf-8

在utf-8编码的文件中添加utf-8编码的文本,

因首行有格式数据,不能直接写在执行的脚本文件里,要存到单独的文件里,并且舍弃第一行,例:

sed -n "1,/abc/p" input_file >> tmp_file    #第一部分
sed -n "1!p" append_txt >> tmp_file         #要添加的数据
sed -n "1,/abc/!p" >> tmp_file              #剩下的部分
mv tmp_file input_file                      #重命名

同理,如果是匹配字符串也是utf-8编码,也要先用这种方式事,先将pattern字符串以及目标字符串都以utf-8编码方式保存到单独的文件中,

再(通过sed)读取到变量中处理,读取的时候可以指定行,如:

PATTERN="$(sed "3p")"

也可用一定格式来描述,如:":pattern=不知道:dest=没关系:",然后在行循环中通过如下的方式获得相关数据:

PATTERN=$(sed -n "s/:pattern=\([^:]*\):.*/\1/Ip")
DEST=$(sed -n "s/:dest=\([^:]*\):.*/\1/Ip")

同时sed的输出文件需要事先以utf-8编码的方式创建好,并且不能用覆盖方式,同时sed的输出文件需要事先以utf8编码的方式创建好,并且不能用覆盖方式

或者用sed二进制的方式强制确定文件头,如:

echo -e -n "\xEF\xBB\xBF" > output_file.txt
LINE_NUM=0
while read LINE
do
    LINE_NUM=$(expr ${LINE_NUM} + 1)
    PATTERN=$(echo "${LINE}" | sed -n "s/.*:pattern=\([^:]*\):.*/\1/Ip")
    DEST=$(echo "${LINE}" | sed -n "s/.*:dest=\([^:]*\):.*/\1/Ip")
    if test -z "${PATTERN}" -o -z "${DEST}"; then
        echo "line_num=${LINE_NUM} invalid format : ${LINE}"
        continue
    fi
    sed -n "s/${PATTERN}/${DEST}/p" data_file.txt >> output_file.txt
done<

直接处理二进制/十六进制

s 's/\x11\x22/\xAA\xBB/g' binfile > new_binfile
#\x5B是'[',前面要加转义符,下面两项等价
sed "s/\x0A\\\x5b\x41/abc/g" a.txt
sed "s/\x0A\[\x41/abc/g" a.txt

直接对指定行做处理

sed "1s/\x11\x11\x11/\xEF\xBB\xBF" a.txt    #第一行
sed "1i\\\xEF\xBB\xBF" a.txt    
sed "1a\\\x11\x22\x33" a.txt
sed "\$a\\\x11\x22\x33" a.txt               #最后一行
sed '$a\\\x11\x22\x33' a.txt
sed "10r /root/test.txt" a.txt > b.txt      #在第10行插入文件

行范围

sed -n '5,10{/pattern/p}' file
sed -n '1,/^tagname$/!p' file
sed -n "/aaa/,/bbb/{=;p;}" file     #全局每一个aaa和bbb行之间的行都会被输出
sed -n "/ccc/,\$wccc.out" file  ccc到最后一行

只匹配一次

echo  "aasdfasdfasdf" | sed -n "/^Revision: /{s/^Revision: \(.*\)$/\1/p;q;}"

分离文件内容,将 ###aaa_start 行到 ###aaa_end 行的内容输出到 aaa.txt 文件,###bbb_start 行到 ###bbb_end 行的内容输出到 bbb.txt 文件,

两文件内容允许交叉重叠,也就是说每一行都会交给两个表达式处理

sed -n -e "/###aaa_start/,/###aaa_end/waaa.out" -e "/###bbb_start/,/###bbb_end/wbbb.out" data.txt

aaa.out文件和bbb.out文件的内容不能重叠,否则无法正确的匹配到bbb.out的开始行

sed -n "
/###aaa_start/{
    :tag_a_loop;
    waaa.out
    n;
    /###aaa_end/{
        waaa.out
        btag_a_end;
    }
    btag_a_loop;
    :tag_a_end;
};
/###bbb_start/{
    :tag_b_loop;
    wbbb.out
    n;
    /###bbb_end/{
        wbbb.out
        btag_b_end;
    }
    btag_b_loop;
    :tag_b_end;
};" data.txt

不包含首尾标题行

sed -n "
/###aaa_start/{
    :tag_a_loop;
    n;
    /###aaa_end/!{
        waaa.out
        btag_a_loop;
    }
};
/###bbb_start/{
    :tag_b_loop;
    n;
    /###bbb_end/!{
        wbbb.out
        btag_b_loop;
    }
};
" data.txt

某一行到文件末尾都保存成一个文件

sed -n -e "/###aaa_start/,/###aaa_end/waaa.out" -e "/###bbb_start/,/###bbb_end/wbbb.out" -e "/###ccc_start/,\$wccc.out" data.txt

不保存收尾标记的行

sed -n "
/###aaa_start/{
    :tag_a_loop;
    n;
    /###aaa_end/!{
        waaa.out
        btag_a_loop;
    }
};" data.txt

在原来行之前插入行号,或者用grep -n

sed = test.txt | sed 'N;s/\n/\t/'

插入空行

在匹配式样“regex”的行之前插入一空行

sed '/regex/{x;p;x;}'

在匹配式样“regex”的行之后插入一空行

sed '/regex/G'

在匹配式样“regex”的行之前和之后各插入一空行

sed '/regex/{x;p;x;G;}'

你可能感兴趣的:(sed note)