.uncrustify.cfg
더 읽기 쉽도록 파일을 편집하고 있습니다 . 다음과 같이 다시 포맷하고 싶습니다.
두 줄:
# Add or remove between the parens in the function type: 'void (*x)(...)'
sp_after_tparen_close = ignore # ignore/add/remove/force
한 줄 출력:
sp_after_tparen_close = ignore # ignore/add/remove/force# Add or remove between the parens in the function type: 'void (*x)(...)'
Perl이 최선의 선택인 것처럼 보였지만 구문에 압도당했습니다. 10년의 여유가 생기면 배우겠습니다 ;-)
좀 더 일반화하려면 다음과 같이 하세요.
두 줄:
#a comment line
some code
한 줄 출력:
some code # a comment line
==========================
John: 손으로 그린 두 줄:
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를 사용하지 않고 두 쌍을 결합했습니다.
# 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'
이것은 질문의 간단한 예를 처리합니다. 주석이 아니고 최소한 하나의 문자를 포함하는 줄이 뒤에 오는 모든 주석 줄은 그 뒤의 줄에 추가됩니다.
따라서 예제를 실행하면 출력은 다음과 같습니다.
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
- 개행 문자가 이어집니다...\([^#].*\)
- 해시가 아닌 문자가 하나 이상 있고#
패턴 공간에 모든 것이 남아 있습니다.- 그리고
\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
이 스크립트는 이전 행을 보유하는 단일 변수를 사용합니다 . 간단히 말해서, 각 줄을 반복하면서 마지막 줄이 주석이고 현재 줄이 주석이 아니면 두 줄을 함께 인쇄합니다. 그렇지 않으면 마지막 줄을 인쇄합니다.
/^[[: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
및 관련 논리가 필요하지 않습니다.