.uncrustify.cfg
読みやすくするためにファイルを編集しています。次のように再フォーマットしたいと思います。
2行:
# Add or remove between the parens in the function type: 'void (*x)(...)'
sp_after_tparen_close = ignore # ignore/add/remove/force
1行出力:
sp_after_tparen_close = ignore # ignore/add/remove/force# Add or remove between the parens in the function type: 'void (*x)(...)'
Perlが最良の選択だったようですが、構文に圧倒されました。 10年の余裕があれば学びます ;-)
もっと一般化するには、次のようにします。
2行:
#a comment line
some code
1行出力:
some code # a comment line
==========================
John:手描きの2行:
nl_while_brace = ignore # I,A,R,F # Add or remove newline between 'while' and '{'
nl_scope_brace = ignore # I,A,R,F # Add or remove newline between 'scope (x)' and '{' (D)
...awkを使用せずに2つのペアを組み合わせました。
# Add or remove newline between 'unittest' and '{' (D)
nl_unittest_brace = ignore # I,A,R,F
# Add or remove newline between 'version (x)' and '{' (D)
nl_version_brace = ignore # I,A,R,F
答え1
sed '/^#/N;s/\(.*\)\n\([^#].*\)/\2 \1/;P;D'
これは質問の簡単な例を扱います。コメントではなく、少なくとも1つの文字を含む行が続くすべてのコメント行は、その後の行に追加されます。
したがって、例を実行すると、出力は次のようになります。
sp_after_tparen_close = ignore # ignore/add/remove/force # Add or remove between the parens in the function type: 'void (*x)(...)'
@John1024の例を実行すると、出力は次のようになります。
#
# Some comments
#
sp_after_tparen_close = ignore # ignore/add/remove/force # Add or remove between the parens in the function type: 'void (*x)(...)'
some code #a comment line
more code
# comment one
# comment two
still more code # comment three
これらのケースを処理するためにsed
ループは必要ありません。この場合、\n
ewline文字を含めることができる唯一の行は、ハッシュで始まる行です。なぜなら、この行に 1 が追加される#
唯一の行だからです。sed
sed
ハッシュで始まる行に出会ったら、追加の入力行を取得#
してN
パターン空間に追加します。sed
次に、次のs///
ものを交換してみてください。
\(.*\)
- できるだけ多くの引用を使用し、\1
その後に...\n
- 改行文字が続きます...\([^#].*\)
- ハッシュ以外の文字が1つ以上あり、#
パターン空間にすべてが残っています。- そして
\2 \1
。
sed
次に、P
最初に表示される\n
ewline文字までパターンスペースを印刷し、D
同じ文字を削除して残りを再試行します。(そうであれば)。
答え2
私はこれがあなたが望むことをすると信じています:
awk '/^[[:space:]]*[^#]/ && last ~ /^#/ {printf "%s %s",$0,last; last="";next} {print last; last=$0} END{print last}' sample.cfg
たとえば、次の入力ファイルがあるとします。
#
# Some comments
#
# Add or remove between the parens in the function type: 'void (*x)(...)'
sp_after_tparen_close = ignore # ignore/add/remove/force
#a comment line
some code
more code
# comment one
# comment two
# comment three
still more code
出力は次のとおりです
$ awk '/^[[:space:]]*[^#]/ && last ~ /^#/ {printf "%s %s",$0,last; last="";next} {print last; last=$0} END{print last}' uncrustify.cfg
#
# Some comments
#
sp_after_tparen_close = ignore # ignore/add/remove/force # Add or remove between the parens in the function type: 'void (*x)(...)'
some code #a comment line
more code
# comment one
# comment two
still more code # comment three
どのように動作しますか?
awk
ファイルの各行を暗黙的に繰り返します。
last
このスクリプトは、前の行を保持する単一の変数を使用します。簡単に言えば、各行を繰り返しながら、最後の行がコメントであり、現在の行がコメントでない場合は、2行を一緒に印刷します。それ以外の場合は、最後の行を印刷します。
/^[[:space:]]*[^#]/ && last ~ /^#/ {printf "%s %s",$0,last; last="";next}
(a)この行がコメントではなく(b)前(最後)の行がコメントの場合、最後の行と現在の行が結合されて印刷されます。それ以降は
last
クリア可能です。その後、残りのコマンドをスキップしてジャンプして再起動しますnext
。{print last; last=$0}
それ以外の場合は、その
last
行を印刷します。last
現在行の内容で更新されます。END{print last}
ファイル内のすべての行を繰り返してから、その
last
行の内容を印刷します。
他の例
次の入力を考慮してください。
# Add or remove newline between 'unittest' and '{' (D)
nl_unittest_brace = ignore # I,A,R,F
# Add or remove newline between 'version (x)' and '{' (D)
nl_version_brace = ignore # I,A,R,F
出力は次のとおりです
$ awk '/^[[:space:]]*[^#]/ && last ~ /^#/ {printf "%s %s",$0,last; last="";next} {print last; last=$0} END{print last}' new
nl_unittest_brace = ignore # I,A,R,F # Add or remove newline between 'unittest' and '{' (D)
nl_version_brace = ignore # I,A,R,F # Add or remove newline between 'version (x)' and '{' (D)
答え3
私の意見によれば、コマンドラインを操作するよりも短いスクリプトでこのようなものを開発するのが最も簡単です。さらに、保管することもできます。
#!/usr/bin/perl
use strict;
use warnings FATAL => qw(all);
my $buffer = "";
my $linesBuffered = 0;
while (<STDIN>) {
# Check if this line is a just a comment.
if ($_ =~ /^\s*#/) {
# Assume multi-line comments should not be appended.
if ($buffer) { $buffer .= $_ }
else { $buffer = $_ }
$linesBuffered++;
} else {
if ($linesBuffered > 1) {
# Print multi-line comment.
print "$buffer$_";
# Reset buffer.
$buffer = "";
$linesBuffered = 0;
} elsif ($buffer) {
# Print buffered line with comment trailing.
chomp $_;
print "$_ $buffer";
# Reset buffer.
$buffer = "";
$linesBuffered = 0;
} else { print $_ }
}
}
print $buffer if ($buffer);
たとえば、これを使用できます./filter.pl < .uncrustify.cfg > .uncrustify.copy
。これはまだ完了していないので、cp .uncrustify.copy .uncrustify.cfg
満足している場合は後で行う必要があります。標準入力から読み取るのでテストできます。
> ./filter.pl
what <- stdin
what <- stdout
ここではコメントではないので、すぐにその行を吐き出します。次の例では、stdinとstdoutを指摘しません。
#okay
then
then #okay
この場合、コメント行をバッファリングして次の(コメントではなく)行に追加します。
#foo
#bar
#foo
#bar
この場合、複数行のコメントを出力します。
今数時間:
- Perlでは、空の文字列(
""
)がfalseをテストします。 /^\s*#/
0個以上のスペースで始まり、後ろに#
。- edでない限り
chomp
、入力行の末尾に改行文字があるはずです。
以下はJohn1024の例の出力です。
#
# Some comments
#
sp_after_tparen_close = ignore # ignore/add/remove/force # Add or remove between the parens in the function type: 'void (*x)(...)'
some code #a comment line
more code
# comment one
# comment two
# comment three
still more code
どこに注目してください# comment three
これはJohn1024とmikeservの出力に関連しています。これは意図的ですが、その値は要件によって異なります。ここで私が好むのは、次のコード行の前に複数行コメントの最後の行を追加してはいけないと仮定することです。一つの線コードの後ろにあるコメントが移動されました。これを行うと、スクリプトがより複雑になります。それ以外の場合、変数$linesBuffered
と関連ロジックは必要ありません。