如何查找和打印具有严格模式的行是合适的

时间:2012-10-08 09:54:06

标签: sed pattern-matching strict busybox

问题如下。有一个包含一组字符串的文件 testfile的:

string2 var var33
string2 HD loop 334
000:000:7878:7878:8978
string1 var var33    
string1 HD loop
000:000:7878:7878:8978
string3 var var33
string3 HD loop4343
000:000:7878:7878:8978

需要找到具有严格模式的行是合适的,例如“HD循环”,然后输出在线上和之后找到的字符串。换句话说,结果应如下所示:

string1 var var33
string1 HD loop
000:000:7878:7878:8978

6 个答案:

答案 0 :(得分:1)

也许您正在寻找上下文 max_count 。使用GNU grep

grep -C 1 -m 1 "HD loop" file.txt

如果您只想输出匹配的行及其后面的行:将-C 1更改为-A 1

编辑:

grep -P -C 1 "\bHD loop\b" file.txt

编辑:

grep -C 1 "[^a-zA-Z0-9_]HD loop[^a-zA-Z0-9_]" file.txt

答案 1 :(得分:0)

awk中的shell

awk '
    {
        arr[c++] = $0
    }
    END{
        for (a in arr) {
            if (arr[a] ~ "HD loop") {
                printf("%s\n%s\n%s\n", arr[a-1], arr[a], arr[a+1])
                exit
             }
        }
    }
' FILE

另一种实现,无需填充太多RAM:

awk '
    {
        if ($0 ~ "HD loop") {
            print var
            print $0
            getline
            print
            exit
        }
        else{
            var=$0
        }
    }
' FILE

答案 2 :(得分:0)

由于您要求的是sed计划,因此这里提供了您所寻求的答案

sed -n -f xfile.sed xfile.txt

其中 xfile.txt 是您的示例输入文件, xfile.sed

H
/HD loop/{
  x
  p
  n
  p
  q
}

答案 3 :(得分:0)

使用sed:

#!/bin/sed -nf

/HD loop$/ {
    x
    G
    N
    p
    s/.*\n\([^\n]*\)/\1/
}
h

当在行的末尾找到“HD循环”(由$字符指示)时,执行命令块。此命令块首先使用x交换命令,使用模式空间(工作缓冲区)的内容交换保留空间(辅助缓冲区)的内容。正如我们稍后将看到的,我们将保持最后一行读取的保留空间。 G命令会将保留空间的内容(现在包含当前行)附加到模式空间中,N命令将读取输入的下一行并将其附加到模式中空间。然后我们可以使用p命令打印模式空间。最后要做的是恢复保留空间。我们使用两个命令执行此操作。第一个是替换命令,它从模式空间中删除除最后一行之外的所有行。然后我们使用h命令复制模式空间以保留空间。

即使该行与“HD循环”不匹配,也会将其复制到保留空间。通过执行此操作,保留空间将始终包含上一行的内容。请注意,由于我们在找到匹配项后设置保留空间的方式,它无法正确识别连续行上出现的两个匹配项。如果你想考虑这个问题,需要一些特殊的处理方法:

#!/bin/sed -nf

/HD loop$/ b next
h

:start
n

/HD loop$/ {
    x
    G
    :next
    N
    p
    s/.*\n\([^\n]*\)/\1/
    /HD loop$/ b next
    d
}
h
b start

对于更完整和通用的版本,我们必须首先考虑在第一行找到“HD循环”时会发生什么。在之前的版本中,它将打印一个空行,然后是“HD loop”行。因为这可能会混淆输出,认为HD循环实际上是一个空行,我们必须对此进行特殊处理。特殊处理是使用我们自己的方法来覆盖sed的评估循环。

我们使用start命令定义:标签,该命令定义循环的开始。然后,在脚本结束时,我们使用b分支命令跳回到循环的开始。为了完全模仿sed的评估循环,start标签之后的第一个命令是n next命令,将下一个输入行读入模式空间。

通过定义循环,我们可以处理第一个特殊情况,即第一行以HD循环开始。如果是这样,我们必须跳过加载保留空间的内容,因为我们知道它不包含任何有用的数据。让我们在next命令之后定义标签G以附加保留空间的内容。我们现在可以使用/HD loop/ b next跳过保持空间操作,只打印当前行和后面的行。

如果第一行没有以“HD loop”开头,我们必须在n用另一个命令替换之前将它存储到保留空间。所以我们使用h命令。

下一个特殊情况是两条“HD loop”线相互出现。在这种情况下,在上一版本的块的末尾,我们可以检查新读取的行是否包含“HD循环”,如果是,我们可以简单地按顺序跳回next标签阅读另一行并打印出来。我们可以多次执行此操作,处理多个连续的“HD循环”线路。

最后一种特殊情况是两条“HD loop”线条出现一条线。如果我们保持原样,这种情况将在“HD循环”行之间打印两次。要对此进行处理,如果在匹配后立即找到“HD循环”线,我们必须表现得好像不需要打印保留空间。因为这种情况类似于我们查看输入的第一行时发生的情况,我们可以在匹配结束时使用d删除命令来清除模式空间并重新启动整个脚本。现在它的行为好像该行是第一个输入行,如果匹配后的行是“HD循环”行,则不会打印保留空间。

更新:如果您只想要第一个结果,可以简化以下几点:

#!/bin/sed -nf

/HD loop$/ b next
h

:start
n

/HD loop$/ {
    x
    G
    :next
    N
    p
    q
}
h
b start

现在,我们可以使用q命令退出,而不是在打印行之后执行所有先前的操作。

希望这有助于=)

答案 4 :(得分:0)

awk '{for(i=1;i<NF;i++)if($i" "$(i+1)=="HD loop"){print x;print;getline;print}};{x=$0}' your_file

测试如下:

> cat temp
    000:000:7878:7878:8978
    string1 var var33    
    string1 HD loop
    000:000:7878:7878:8978
    string3 var var33
    string3 HD loop4343
    000:000:7878:7878:8978

> awk '{for(i=1;i<NF;i++)if($i" "$(i+1)=="HD loop"){print x;print;getline;print}};{x=$0}' temp
    string1 var var33    
    string1 HD loop
    000:000:7878:7878:8978

答案 5 :(得分:0)

这可能适合你(GNU sed):

sed '$!N;/HD loop$/!D;$!N;p;d' file