【问题标题】:delete everyting above the pattern删除图案上方的所有内容
【发布时间】:2013-09-30 14:47:44
【问题描述】:

我的问题是从三个模式中决定首先出现的模式,并删除第一个模式之前的所有内容,同样删除最后一个模式之后的所有内容。

我知道可以使用以下命令删除上述模式的所有内容:

sed -n '/pattern/,$p' input  

grep -E -m1 "pattern1|pattern2|pattern3" 将打印包含第一个模式的行,我想我必须将此命令的输出提供给sed 的某些变体,但不知道该怎么做。

  1. 模式1
  2. 模式2
  3. 模式3

Line1 这是一个示例行,没有任何意义,请忽略
Line2 仅用于提供示例 PATTERN2 以使我的查询对所有人都清楚
Line3 这是一个示例行,例如没有任何意义请忽略
Line4 仅用于提供示例 pattern1 以使我的查询对所有人都清楚
Line5 这是一个示例行,没有任何意义请忽略
Line6 仅用于提供示例 pattern1 以使我的查询对所有人都清楚
Line7 这是一个示例行,没有任何意义,请忽略
Line8 仅用于提供示例 pattern2 以使我的查询对所有人都清楚
Line9 这是一个示例行,没有任何意义请忽略
Line10 仅用于提供示例 pattern3 以使我的查询对所有人都清楚
Line11 仅用于提供示例 PATTERN2 以使我的查询对所有人都清楚
Line12 仅用于提供示例 pattern1 以使我的查询对所有人都清楚
Line13 仅用于提供示例 pattern3 以使我的查询对所有人都清楚
第 14 行仅用于举例说明我的查询对所有人都清楚

期望的输出:

如果第一个模式是 PATTERN2 并且 pattern3 是三个模式中的最后一个模式,那么下面将是所需的输出:

Line2 仅用于提供示例 PATTERN2 以使我的查询对所有人都清楚
Line3 这是一个示例行,例如没有任何意义请忽略
Line4 仅用于提供示例 pattern1 以使我的查询对所有人都清楚
Line5 这是一个示例行,没有任何意义请忽略
Line6 仅用于提供示例 pattern1 以使我的查询对所有人都清楚
Line7 这是一个示例行,没有任何意义,请忽略
Line8 仅用于提供示例 pattern2 以使我的查询对所有人都清楚
Line9 这是一个示例行,没有任何意义,请忽略 Line10 仅用于提供示例 pattern3 以使我的查询对所有人都清楚
Line11 仅用于提供示例 PATTERN2 以使我的查询对所有人都清楚
Line12 仅用于提供示例 pattern1 以使我的查询对所有人都清楚
Line13 仅用于提供示例 pattern3 以使我的查询对所有人都清楚

【问题讨论】:

  • 模式是字符串还是正则表达式?一种模式可以包含在另一种模式中吗?模式需要是一个完整的单词吗?模式匹配是否必须区分大小写或不区分大小写(如您的示例所示)?
  • 您的以下解决方案在我的脚本中完美运行。谢谢

标签: unix sed awk html-table


【解决方案1】:

sed 是用于在单行上进行简单替换的出色工具,但对于其他任何事情,只需使用 awk。您没有提供任何示例输入或预期输出或任何有关“模式”含义的信息,所以这是一个未经测试的猜测,但也许它对您有用:

awk -v pats='pattern1|pattern2|pattern3' '
    { data[NR] = $0 }
    $0 ~ pats { if (start) end=NR; else start=NR }
    END{ for (i=start; i<=end; i++) print data[i] }
' file

评论版本:

awk -v pats='pattern1|pattern2|pattern3' # or-separated list of patterns to be matched                            
    { data[NR] = $0 }                    # save current line in an array indexed by line number
    $0 ~ pats {                          # IF the current line matches any of the target patterns THEN
        if (start)                       #    IF the start line number is already recorded THEN
            end=NR;                      #        remember the current line number as the last one on which one of the patterns exists
        else                             #    ELSE
            start=NR                     #        remember the current line number as the first one on which one of the patterns exists
                                         #    ENDIF
    }                                    # ENDIF
    END{                                 # Once all of the file has been read into the array
        for (i=start; i<=end; i++)       # Loop through the array, starting at the first line on which one of the patterns was found
                                         # and ending on the last line on which one of the patterns was found
            print data[i]                #     Print the contents of the array at each line number in the loop.
    }
' file

【讨论】:

  • 谢谢这对我有用,你能解释一下上面的 awk 命令吗?
  • 我添加了注释版本。
【解决方案2】:

正如您所展示的,这将删除第一次出现之前的任何内容:

sed -n '/pattern/,$p' file

所以我们可以获取它的输出,反转它并应用 再次编程。然后反转 that 的输出,我们得到了第一个匹配和最后一个匹配之间的所有文本:

seq 10 | sed -n '/4\|7/,$p' | tac | sed -n '/4\|7/,$p' | tac
4
5
6
7

我们可以把它放到一个函数中:

after() { sed -n '/'"$1"'/,$p'; }
between() { after "$1" | tac | after "$1" | tac; }
seq 10 | after '4\|7'
echo ===
seq 10 | between '4\|7'
4
5
6
7
8
9
10
===
4
5
6
7

【讨论】:

    猜你喜欢
    • 2016-04-10
    • 1970-01-01
    • 1970-01-01
    • 2021-12-15
    • 1970-01-01
    • 2012-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多