0

问题如下。有一个带有一组字符串 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 loop”,然后输出在该行及其之后找到的字符串。换句话说,结果应该是这样的:

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

6 回答 6

1

也许您正在寻找contextmax_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
于 2012-10-08T10:50:41.497 回答
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
于 2012-10-08T10:06:52.293 回答
0

既然您要的是一个sed程序,那么这里有一个可以给出您所寻求的答案的程序

sed -n -f xfile.sed xfile.txt

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

H
/HD loop/{
  x
  p
  n
  p
  q
}
于 2012-10-08T10:23:42.870 回答
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
于 2012-10-08T14:01:34.283 回答
0

这可能对您有用(GNU sed):

sed '$!N;/HD loop$/!D;$!N;p;d' file
于 2012-10-08T23:58:59.910 回答
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 loop”时会发生什么。在以前的版本中,它会打印一个空行,然后是“HD loop”行。因为这会使输出混淆,认为 HD 循环实际上前面有一个空行,所以我们必须对此进行特殊处理。特殊处理是使用我们自己的覆盖 sed 的评估循环。

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

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

如果第一行不是以“HD loop”开头的,我们必须先将其存储到保持空间中,然后n再用另一个命令替换它。所以我们用h命令来做到这一点。

下一个特殊情况是两条“HD 循环”线彼此跟随出现。在这种情况下,在之前版本的块末尾,我们可以检查新读取的行是否包含“HD loop”,如果是,我们可以简单地跳回next标签以读取另一行并打印它。我们可以根据需要多次执行此操作,处理尽可能多的连续“高清循环”行。

最后一种特殊情况是两条“HD 循环”线被一条线隔开。如果我们保持原样,这种情况将打印两次“HD loop”行之间的行。为了解决这个问题,如果在匹配后立即找到“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命令退出,而不是在打印该行后执行所有先前的操作。

希望这会有所帮助=)

于 2012-10-08T11:52:14.390 回答