【问题标题】:How do I delete a matching line and the previous one?如何删除匹配的行和上一个?
【发布时间】:2021-03-05 19:58:49
【问题描述】:

我需要删除匹配的一行和它之前的一行。 例如,在下面的文件中,我需要删除第 1 行和第 2 行。

我试过 "grep -v -B 1 "page.of." 1.txt 我希望它不会打印匹配的行和上下文。

我尝试了How do I delete a matching line, the line above and the one below it, using sed?,但无法理解 sed 的用法。

---1.txt--
**document 1**                         -> 1
**page 1 of 2**                        -> 2

testoing
testing

super crap blah

**document 1**
**page 2 of 2**

【问题讨论】:

标签: unix sed grep pattern-matching


【解决方案1】:

你想做一些与answer given非常相似的事情

sed -n '
/page . of ./ { #when pattern matches
n #read the next line into the pattern space
x #exchange the pattern and hold space
d #skip the current contents of the pattern space (previous line)
}

x  #for each line, exchange the pattern and hold space
1d #skip the first line
p  #and print the contents of pattern space (previous line)

$ { #on the last line
x #exchange pattern and hold, pattern now contains last line read
p #and print that
}'

单行

sed -n '/page . of ./{n;x;d;};x;1d;p;${x;p;}' 1.txt

【讨论】:

  • 注意一行可以搞定:sed -n '/page 1/{n;x;d;};x;1d;$G;p' 1.txt
  • @Beta:当然,多余的行之类的只是注释
  • 为什么这被否决了?它做了提问者想要的(并且在 sed 中启动)
【解决方案2】:

grep -v -B1 不起作用,因为它会跳过这些行,但稍后会包含它们(由于 -B1。要检查这一点,请尝试以下命令:

**document 1**                         -> 1
**page 1 of 2**                        -> 2

**document 1**
**page 2 of 2**
**page 3 of 2**

您会注意到page 2 行将被跳过,因为该行不会被匹配,并且下一个like 也不会被匹配。

有一个简单的 awk 解决方案:

awk '!/page.*of.*/ { if (m) print buf; buf=$0; m=1} /page.*of.*/ {m=0}' 1.txt

awk 命令说明如下:

如果当前行有那个“page ... of”,那么它将表明您没有找到有效的行。如果找不到该字符串,则打印上一行(存储在 buf 中)并将缓冲区重置为当前行(因此强制它滞后 1)

【讨论】:

    【解决方案3】:
    grep -vf <(grep -B1 "page.*of" file | sed '/^--$/d') file
    

    【讨论】:

    • 您想将-x 选项添加到外部grep。这不是非常有效。
    【解决方案4】:

    对 sed 不太熟悉,但这里有一个 perl 表达式可以解决问题:

    cat FILE | perl -e '@a = <STDIN>;
                        for( $i=0 ; $i <= $#a ; $i++ ) { 
                         if($i > 0 && $a[$i] =~ /xxxx/) { 
                           $a[$i] = ""; 
                           $a[$i-1] = "";
                         }
                        } print @a;'
    

    编辑:

    其中“xxxx”是您要匹配的内容。

    【讨论】:

    • Cat 的无用用法应该消失了。
    • 是的,这个解决方案的某些部分可能会受到批评,但总体概念是可靠的,示例代码很好地实现了它。这很容易理解。足以让某人开始。这就是答案的全部意义所在。它不需要完美。我喜欢这个答案。它确实帮助我解决了与原始问题类似的问题。
    • 如果你想删除包含xxxx但仅此而已的行,我建议xxxx\rxxxx\r\n以防其他行是xxxxabc
    【解决方案5】:

    谢谢,我正在尝试使用Foo Bah 给出的 awk 命令 删除匹配的行和上一个。我必须多次使用它,所以对于匹配部分我使用一个变量。给定的 awk 命令有效,但是当使用变量时它不起作用(即它不会删除匹配的 & prev. 行)。我试过了:

    awk -vvar="page.*of.*" '!/$var/ { if (m) print buf; buf=$0; m=1} /$var/ {m=0}' 1.txt

    【讨论】:

      猜你喜欢
      • 2015-04-18
      • 2010-10-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-11
      • 1970-01-01
      • 2018-09-13
      • 2021-03-21
      相关资源
      最近更新 更多