入力例:
START{
some text
{
more text}
almost there
}
nothing important{
...
希望の出力:
START{
some text
{
more text}
almost there
}
最初の開いたブラケットは別の位置にある可能性があります。
START{...
START {...
START
{...
先頭には特殊文字を含めることもできます。例: *
{}
STARTから始まるすべての内容と最初の一致の間のすべての内容(bash)を印刷したいと思います。私はそれが見つかると増加し{
、見つかると減少するカウンターを持つと思います}
。結果が0の場合は印刷を停止します(中括弧は常に一致します)。
答え1
すべてのUnixシステムのすべてのシェルで任意のawkで動作する簡単な無差別方法:
$ cat tst.awk
s=index($0,"START") { $0=substr($0,s); f=1 }
f { rec = rec $0 RS }
END {
len = length(rec)
for (i=1; i<=len; i++) {
char = substr(rec,i,1)
if ( char == "{" ) {
++cnt
}
else if ( char == "}" ) {
if ( --cnt == 0 ) {
print substr(rec,1,i)
exit
}
}
}
}
$ awk -f tst.awk file
START{
some text
{
more text}
almost there
}
答え2
そしてpcregrep
:
start_word='START'
pcregrep -Mo "(?s)\Q$start_word\E\h*(\{(?:[^{}]++|(?1))*+\})" < your-file
zsh
組み込み機能を使用します。
set -o rematchpcre
start_word='START'
[[ $(<your-file) =~ "(?s)\Q$start_word\E\h*(\{(?:[^{}]++|(?1))*+\})" ]] &&
print -r -- $MATCH
(?1)
上記で検討した最初のペアの正規表現である(...)
PCREの再帰正規表現機能を使用します。
pcregrep
両方がない場合は、zsh
いつでも次に切り替えることができます。本物(PCREperl
からP
):
perl -l -0777 -sne '
print $& if /\Q$start_word\E\h*(\{(?:[^{}]++|(?1))*+\})/s
' -- -start_word='START' < your-file
(perl
これらのいずれかを除いてすべてが$start_word
含まれていないとします\E
。)