次のファイルがあります。
x = {
y = {
z = {
block = {
line1
line2
line3
}
}
}
}
x2 = {
y2 = {
block = {
line4
line5
}
}
}
xyz
block = {
line6
}
など。ブロック内の行を反転する必要がありますが、他のすべての項目は次のように順番に保持する必要があります。
x = {
y = {
z = {
block = {
line3
line2
line1
}
}
}
}
x2 = {
y2 = {
block = {
line5
line4
}
}
}
xyz
block = {
line6
}
sedまたはawkを使用してこれを行うには?ブロックを逆さまに反転しましたが、再び所定の位置に置くことはできません。
sed -n '/block = {.$/,/}$/p' inputfile | tac
答え1
Perlを使っても大丈夫なら:
perl -ne 'if($f && /}/){$f=0; print @blk};
$f ? unshift(@blk, $_) : print;
if(/block = {/){$f=1; @blk=()}' ip.txt
if(/block = {/){$f=1; @blk=()}
配列を初期化し、入力行に以下が含まれている場合に@blk
フラグを設定します。$f
block = {
$f ? unshift(@blk, $_) : print
このフラグが有効な場合は配列の前に入力行を挿入し@blk
、それ以外の場合は入力行を印刷します。if($f && /}/){$f=0; print @blk}
フラグが有効になっていて入力行に以下が含まれている場合は、フラグを設定解除して配列}
の内容を印刷します。@blk
そしてawk
:
awk 'f && /}/{f=0; for(i=c; i>=1; i--) print blk[i]}
{if(f) blk[++c] = $0; else print}
/block = {/{f=1; c=0}' ip.txt
答え2
インデントを使用してその端をperl
見つけるもう1つの方法は次のとおりです。}
block = {
perl -C -0777 -pe '
s{^(\h*)block = \{\n\K.*?\n(?=\1\}$)}{
join "", reverse $& =~ m{.*\n}g
}gems' < your-file
答え3
sed
コードを書くのは簡単ですが、読みにくいことを証明してください。
sed '/block = {/,/}/{/[{}]/!{G;h;d;};x;s/.$//p;g;s/.*//;x;}' file
予約済みスペースに現在予約済みスペースを追加して、反転する行(中括弧のない行)を収集します(それで順序は自動的に変更されます)。コードは移植可能であり、sed
どの実装でも使用できます。詳細:
/block = {/,/}/
block = {
}
自分で選択したように、次の範囲を選択してください。他のすべての同様のコードはxyz
変更されずに印刷されます。/[{}]/!{G;h;d;}
中かっこなしの行処理(ブロック行):G
現在予約されているスペースを追加し、h
結果を予約済みスペースに移動し、出力とともにそのd
行の処理を停止します。- 残りはサポートラインに対してのみ実行されます。ここで
x
バッファを変更して予約済みスペースの行を印刷し、予約済み空きs/.$//p
スペースに追加して導入された予約済みスペースから末尾の改行を削除する必要があります。 ubstitudeコマンドp
のオプションは、空のs
予約スペースが印刷されるのを防ぐために、正常な置換にのみ印刷されます。最後にg
予約されたスペースから現在の行を復元するために使用されます。 - 最後に、保持スペースを空にする必要があります。
s/.*//;x
:現在の行をh
前のスペースに保存し、パターンスペースを空にしてバッファを交換することで、保持スペースは空になり、パターンスペースには出力用の現在の行が再び含まれます。
答え4
使用幸せ(以前のPerl_6)
~$ raku -ne 'BEGIN my @blk; if (/block/ && .put) { for lines() {
if /\}/ { put join "\n", (@blk.pop xx @blk.elems, $_); last};
@blk.push: $_ }
} else { .put };' file
#OR (more simply)
~$ raku -ne 'BEGIN my @blk; if (/block/ & .put) { for lines() {
if /\}/ { .put for (@blk.pop xx @blk.elems, $_).flat; last};
@blk.push: $_ }
};' file
上記のコードはPerlファミリーの言語であるRakuで書かれています。-ne
非自動印刷フラグを使用して入力を1行ずつ読みます。BEGIN
ブロック内で@blk
配列が宣言され、if
「ブロック」文字列(キーワード)が見つかり、lines
最後}
の閉じ括弧が読み込まれます。読んで配列でlines
編集し、Curlieの終わりが見つかったら完全に(つまり、逆の順序で)閉じます。push
@blk
pop
}
last
入力例:
x = {
y = {
z = {
block = {
line1
line2
line3
}
}
}
}
x2 = {
y2 = {
block = {
line4
line5
}
}
}
xyz
block = {
line6
}
出力例:
x = {
y = {
z = {
block = {
line3
line2
line1
}
}
}
}
x2 = {
y2 = {
block = {
line5
line4
}
}
}
xyz
block = {
line6
}
付録:@Sundeepの優れたPerl5ソリューションのRaku翻訳を探している人は、以下を参照してください。
~$ raku -ne 'BEGIN my @blk; state $f;
if ($f && /\}/) {$f=0; .put for @blk};
$f ?? unshift(@blk, $_) !! .put;
if (/block/) {$f=1; @blk=()};' file