【问题标题】:sed, delete a line which is before anothersed,删除另一行之前的一行
【发布时间】:2016-08-24 07:35:51
【问题描述】:

所以我有这个代码,它是关于 squid 代理的,它寻找与 $DELETE 变量匹配的行。
如果用户输入deleteall 进行确认,则 sed 会删除所有匹配 "s_test" 的行 现在我希望 sed 删除与 $aclonly 变量匹配的行和上面的行,它也可以是变量,它总是以 "#PR[0-9]*" 开头 感谢您的任何建议

Example:
#PR0000
http_access allow s_test                 d_test                  http_port

  function remove(){
source_acl=$(grep $DELETE /etc/squid3/conf.d/$CUSTOMER.conf)
echo $source_acl
acl_only=$(echo $source_acl | cut -f2 -d" ")
echo "#$DELETE = $acl_only"
echo "#FOLGENE ACL/RULES GEFUNDEN"
grep $acl_only /etc/squid3/conf.d/$CUSTOMER.conf
return=$?
if [ "$return" = "0" ];then
        echo "WRITE DELETEALL TO REMOVE SHOWN ALCs/RULES"
        echo "WRITE DELETE TO REMOVE ONLY SOURCE ACL WHICH MATCHES IP"
        read delete
        if [ "$delete" = "deleteall" ];then
                sed -i -e /$acl_only/d /etc/squid3/conf.d/$CUSTOMER.conf
                return=$?
                if [ "$return" = "0" ];then
                        echo DELETE SEQUEZ COMPLETET
                else
                        echo ERROR
                fi
        fi
        if [ "$delete" = "delete" ];then
                sed -i -e /$DELETE/d /etc/squid3/conf.d/$CUSTOMER.conf
                return=$?
                if [ "$return" = "0" ];then
                        echo DELETE SEQUEZ COMPLETET
                else
                        echo ERROR
                fi

        fi
else
echo NO MATCHES

fi
exit

【问题讨论】:

    标签: bash shell sed


    【解决方案1】:

    使用 awk

    您可以为此使用 sed(见下文),但 awk 可能更容易。试试:

    awk -v a="$aclonly" '$0~a{getline; last=$0; next} NR>1{print last} {last=$0} END{if (!(last~a))print last}' file
    

    工作原理

    Awk 隐式地逐行读取文件。该脚本使用两个变量。 a 包含我们要匹配的正则表达式。 last 包含上一行。

    • -v a="$aclonly"

      这定义了一个 awk 变量 a,其值等于 shell 变量 aclonly

    • $0~a{getline; last=$0; next}

      如果当前行 $0 与正则表达式 a ($aclonly) 匹配,则忽略当前行,获取下一行,将 last 设置为新行,然后跳过其余部分命令并跳转到next 行。

    • NR>1{print last}

      如果这不是第一行,则打印上一行,last

    • last=$0

      用当前行的内容$0更新变量last

    • END{if (!(last~a))print last}

      在我们读完文件的最后一行后,打印last,只要它不匹配正则表达式a

    两个例子

    作为第一个测试文件,考虑:

    $ cat file
    Example:
    #PR0000
    http_access allow s_test                 d_test                  http_port
    

    如果我们运行我们的命令,只会打印第一行:

    $ awk -v a="$aclonly" '$0~a{getline; last=$0; next} NR>1{print last} {last=$0} END{if (!(last~a))print last}' file
    Example:
    

    作为第二个例子,考虑这个文件:

    $ cat file2
    Example:
    #PR0000
    http_access allow s_test                 d_test                  http_port
    #PR0000
    http_access allow s_test                 d_test                  http_port
    other
    text
    #PR0000
    http_access allow s_test                 d_test                  http_port
    #PR0000
    http_access allow s_test                 d_test                  http_port
    last
    

    对于这个文件,打印如下:

    $ awk -v a="$aclonly" '$0~a{getline; last=$0; next} NR>1{print last} {last=$0} END{if (!(last~a))print last}' file2
    Example:
    other
    text
    last
    

    使用 sed

    在 sed 中可以使用几乎相同的逻辑:

    sed -n '/s_test/{n; $p; x; d}; x; 1!p; ${x;p;}' file
    

    将此应用于我们的两个测试文件:

    $ sed -n '/s_test/{n; $p; x; d}; x; 1!p; ${x;p;}' file
    Example:
    $ sed -n '/s_test/{n; $p; x; d}; x; 1!p; ${x;p;}' file2
    Example:
    other
    text
    last
    

    【讨论】:

    • 如您所知,最好解释一下您的解决方案。
    【解决方案2】:

    考虑 grep:-B 选项允许您在模式匹配之前指定行数。结合 -n 也给出行号

    grep -n -B 1 模式文件

    结合其他命令只会给你上面模式的行号

    grep -n -B 1 模式文件 |头-n 1 | sed 's/-..*//g'

    然后可以使用 sed 删除行号,其中 N 是行号

    sed 'N d' 文件

    【讨论】:

    • 我喜欢使用 grep 获取行号并将其传递给 sed 以删除行的想法
    猜你喜欢
    • 1970-01-01
    • 2020-11-04
    • 1970-01-01
    • 1970-01-01
    • 2013-09-23
    • 2018-09-05
    • 2022-12-04
    • 2017-03-14
    • 2014-03-22
    相关资源
    最近更新 更多