搜索字符串并打印范围内前后的所有内容

rod*_*igo 10 sed text-processing

我有这个文件:

sometext1{
string1
}

sometext2{
string2
string3
}

sometext3{
string4
string5
string6
}
Run Code Online (Sandbox Code Playgroud)

我想在此文件中搜索特定字符串并打印此字符串之前到开头的{所有内容以及此字符串之后到结尾的所有内容}。我试图用 sed 来实现这一点,但如果我尝试打印范围内的所有内容,/{/,/string2/例如 sed 打印:

sometext1{
string1
}

sometext2{
string2
sometext3{
string4
string5
string6
}
Run Code Online (Sandbox Code Playgroud)

如果我搜索字符串“string2”,我需要输出为:

sometext2{
string2
string3
}
Run Code Online (Sandbox Code Playgroud)

谢谢。

mik*_*erv 10

这里有两个命令。如果您想要一个可以修剪到.*{$序列中最后一行的命令(如 @don_crissti 对ed),您可以执行以下操作:

sed 'H;/{$/h;/^}/x;/{\n.*PATTERN/!d'
Run Code Online (Sandbox Code Playgroud)

...它的工作原理是将每一行附加到ewline 字符H后面的旧空间,为匹配的每一行\n覆盖h旧空间{$,并为匹配的每一行交换h旧空间和模式空间^}- 从而刷新其缓冲区。

它只打印匹配该行{\newline,然后PATTERN在某个时刻-这只是没有发生过紧跟在缓冲交换。

它将一系列{$匹配中的任何行删除到序列中的最后一行,但您可以获得所有这些行,例如:

sed '/PATTERN.*\n/p;//g;/{$/,/^}/H;//x;D'
Run Code Online (Sandbox Code Playgroud)

它所做的是h为每个...{$.*^}.*序列交换模式和旧空间,将序列中的所有行附加到ewline 字符H之后的旧空间\n,并在每个行循环中删除模式空间中D第一个出现的\newline 字符,然后再从剩余的开始。

当然,它\n在模式空间中获得ewline的唯一时间是当输入行匹配时^}- 范围的末尾 - 因此当它在任何其他情况下重新运行脚本时,它通常只会拉入下一个输入行。

但是,当PATTERN在与\newline相同的模式空间中找到时,它会在^}再次覆盖之前打印批次(因此它可以结束范围并刷新缓冲区)

鉴于此输入文件(感谢唐)

sometext1{
string1
}

sometext2{
PATTERN
string3
}

sometext3{
string4
string5
string6
}

Header{
sometext4{
some string

string unknown

here's PATTERN and PATTERN again
and PATTERN too
another string here
}
}
Run Code Online (Sandbox Code Playgroud)

第一个打印:

sometext2{
PATTERN
string3
}
sometext4{
some string

string unknown

here's PATTERN and PATTERN again
and PATTERN too
another string here
}
Run Code Online (Sandbox Code Playgroud)

……第二个……

sometext2{
PATTERN
string3
}
Header{
sometext4{
some string

string unknown

here's PATTERN and PATTERN again
and PATTERN too
another string here
}
Run Code Online (Sandbox Code Playgroud)


don*_*sti 6

这是一个解决方案ed

ed -s filename <<< $'g/PATTERN/?{?,/}/p\nq\n'
Run Code Online (Sandbox Code Playgroud)

那是:

g/PATTERN/     # mark each line matching PATTERN  
?{?,/}/p       # for each marked line, print all lines from the previous { up to the next }  
q              # quit editor
Run Code Online (Sandbox Code Playgroud)

这假设PATTERN每对之间只有一条线,{ }否则对于PATTERN同一块内的每条附加线,您将获得重复的输出。
它将适用于{ }包含单行匹配的多个,PATTERN例如具有PATTERN两个不同部分的测试文件:

sometext1{
string1
}

sometext2{
PATTERN
string3
}

sometext3{
string4
string5
string6
}

Header{
sometext4{
some string

string unknown

here's PATTERN again

another string here
}
}
Run Code Online (Sandbox Code Playgroud)

跑步

ed -s sample <<< $'g/PATTERN/?{?,/}/p\nq\n'
Run Code Online (Sandbox Code Playgroud)

输出:

sometext2{
PATTERN
string3
}
sometext4{
some string

string unknown

here's PATTERN again

another string here
}
Run Code Online (Sandbox Code Playgroud)