SED:在比赛前解决两条线路问题

时间:2013-12-28 19:47:19

标签: regex unix sed

打印线,位于比赛前2行(模式)。

我接下来试过了:

sed -n ': loop
/.*/h
:x
{n;n;/cen/p;}
s/./c/p
t x
s/n/c/p
t loop
{g;p;}
' datafile

6 个答案:

答案 0 :(得分:4)

剧本:

  sed -n "1N;2N;/XXX[^\n]*$/P;N;D"

的工作原理如下:

  • 将第一个三个行读入模式空间1N;2N
  • 在最后一行的任何位置搜索测试字符串XXX,如果找到,则打印模式空间的第一行P
  • 将下一行输入附加到模式空间N
  • 从模式空间中删除第一行并重新启动循环而不进行任何新阅读,D,注意1N;2N不再适用

答案 1 :(得分:3)

这可能适合你(GNU sed):

sed -n ':a;$!{N;s/\n/&/2;Ta};/^PATTERN\'\''/MP;$!D' file

这将在整个文件的PATTERN之前打印第2行。

答案 2 :(得分:3)

这一个用grep,更简单的解决方案,易于阅读[但需要使用一个管道]: grep -B2 'pattern' file_name | sed -n '1,2p'

答案 3 :(得分:1)

如果你可以使用awk试试这个:

awk  '/pattern/ {print b} {b=a;a=$0}' file

这将在pattern

之前打印两行

答案 4 :(得分:0)

我已经测试了你的命令,但结果很奇怪(显然是错误的),你没有给出任何解释。您必须在缓冲区中保存三行(名为保留空间),使用最新行进行模式搜索,如果匹配则打印最旧的行:

sed -n '
    ## At the beginning read three lines.
    1 { N; N }
    ## Append them to "hold space". In following iterations it will append
    ## only one line.
    H 
    ## Get content of "hold space" to "pattern space" and check if the 
    ## pattern matches. If so, extract content of first line (until a 
    ## newline) and exit.
    g
    /^.*\nsix$/ { 
        s/^\n//
        P
        q 
    }
    ## Remove the old of the three lines saved and append the new one.
    s/^\n[^\n]*//
    h
' infile

假设并输入文件(infile),内容如下:

one
two
three
four
five
six
seven
eight
nine
ten

它将搜索six,因为输出将产生:

four

答案 5 :(得分:0)

以下是其他一些变体:

awk '{a[NR]=$0} /pattern/ {f=NR} END {print a[f-2]}' file

这会将所有行存储在数组a中。找到模式时存储行号 然后在文件中打印该行号 使用大文件时PS可能会很慢

这是另一个:

awk 'FNR==NR && /pattern/ {f=NR;next} f-2==FNR' file{,}

这会两次读取文件(file{,}file file相同)
在第一轮,它在变量f中找到模式和存储行号 然后在第二轮,它在f

中的值之前打印第二行