sed,删除一个在另一个之前的行

时间:2016-08-24 07:35:52

标签: bash shell sed

所以我有这个代码,它是关于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

2 个答案:

答案 0 :(得分: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

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

  • 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

答案 1 :(得分:0)

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

  

grep -n -B 1模式文件

与其他命令结合使用,只会给出模式上方行的行号

  

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

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

  

sed'n d'文件