我有这个文件:
sometext1{
string1
}
sometext2{
string2
string3
}
sometext3{
string4
string5
string6
}
我想在这个文件中搜索特定的字符串,并打印该字符串之前到开头的所有内容{
以及该字符串之后到结尾的所有内容}
。我尝试使用 sed 来实现此目的,但如果我尝试打印范围内的所有内容,/{/,/string2/
例如 sed 会打印以下内容:
sometext1{
string1
}
sometext2{
string2
sometext3{
string4
string5
string6
}
如果我搜索字符串“string2”,我需要输出为:
sometext2{
string2
string3
}
谢谢。
答案1
这里有两个命令。如果你想要一个命令来修剪到.*{$
序列中的最后一行(正如 @don_crissti 所做的那样ed
)你可以做:
sed 'H;/{$/h;/^}/x;/{\n.*PATTERN/!d'
...其工作原理是将每一行附加到ewline 字符H
后面的旧空间\n
,覆盖h
匹配的每一行的旧空间{$
,并为匹配的每一行交换h
old 和模式空间^}
- 从而刷新其缓冲区。
它只打印与{
then \n
ewline 和 thenPATTERN
在某个点匹配的行 - 并且这只在缓冲区交换后立即发生。
它会删除一系列{$
匹配中的任何行,直到序列中的最后一个,但您可以获得所有包含的行,例如:
sed '/PATTERN.*\n/p;//g;/{$/,/^}/H;//x;D'
它的作用是交换h
每个序列的模式和旧空格...{$.*^}.*
,将序列中的所有行附加到旧行字符H
后面的旧空格\n
,并在每个行循环中D
删除\n
模式空间中第一个出现的 ewline 字符,然后再从剩余的内容开始。
当然,它\n
在模式空间中获得 ewline 的唯一一次是当输入行匹配时^}
(范围的末尾),因此当它在任何其他情况下重新运行脚本时,它只会像往常一样拉入下一个输入行。
但是,当PATTERN
在与 ewline 相同的模式空间中找到时,它会在再次\n
覆盖它之前打印该批次^}
(这样它可以结束范围并刷新缓冲区)。
给定这个输入文件(谢谢唐):
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
}
}
第一个打印:
sometext2{
PATTERN
string3
}
sometext4{
some string
string unknown
here's PATTERN and PATTERN again
and PATTERN too
another string here
}
...还有第二个...
sometext2{
PATTERN
string3
}
Header{
sometext4{
some string
string unknown
here's PATTERN and PATTERN again
and PATTERN too
another string here
}
答案2
这是一个解决方案ed
:
ed -s filename <<< $'g/PATTERN/?{?,/}/p\nq\n'
那是:
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
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
}
}
跑步
ed -s sample <<< $'g/PATTERN/?{?,/}/p\nq\n'
输出:
sometext2{
PATTERN
string3
}
sometext4{
some string
string unknown
here's PATTERN again
another string here
}
答案3
和pcregrep
:
pcregrep -M '(?s)\{[^}]*PATTERN.*?\}'
或者使用 GNU grep
,前提是输入不包含 NUL 字节:
grep -Poz '.*(?s)\{[^}]*PATTERN.*?\}'
答案4
$ awk 'BEGIN{RS="\n\n"; FS="[{}]"} {if ($2 ~ /string4/) {print $2}}' t1.txt
string4
string5
string6
在哪里:
string4
--> 需要匹配的字符串t1.txt
--> 包含查询中提到的文件内容