현재 내 파일에는 다음과 같은 섹션이 포함되어 있습니다.
code statement1
code statement2
# BEGIN SOMENAME
some code
some other code
# END SOMENAME
code statement n +1
code statement n +1
내가하고 싶은 것은 사이의 내용을 주석 처리하는 것입니다.
# BEGIN SOMENAME
그리고
# END
그래서 결국 다음과 같이 보입니다.
code statement1
code statement2
# BEGIN SOMENAME
# some code
# some other code
# END SOMENAME
code statement n +1
code statement n +1
awk
또는 를 사용하여 이를 달성 할 수 있습니까 sed
? 다시 "댓글 달기"만 하면 쉽게 되돌릴 수 있나요?
제가 피하고 싶은 것은 실수하는 것입니다. 따라서 이 줄이 이미 주석 처리되어 있으면 그대로 두어야 합니다. 또한 "주석 입력"에서 end와 start 사이의 줄이 로 시작하지 않으면 무언가를 시도해서는 안 됩니다 #
.
가능한 해결책을 찾았습니다.
awk '
BEGIN {
i=0;
line_with_no_comment_found=0
}
/^# END/ {
m=0;
if ( line_with_no_comment_found == 1 ) {
for (var in a) print "# "a[var]
} else {
for (var in a) print a[var]
}
delete a;
i=0;
line_with_no_comment_found=0;
}
/^# / {
if (m==0) {
print
} else {
a[i++]=$0;
}
}
!/^# / {
if (m==0) {
print
} else {
a[i++]=$0;
line_with_no_comment_found=1
}
}
/^# BEGIN ([a-zA-Z_])([1-9][0-9]*)*/ {
m=1;
}
END { }
'<<EOF
답변1
이 스크립트는 저에게 효과적입니다. 나는 이것을 GNU Awk 4.0.1에서 테스트했지만 Nawk에서도 작동할 것입니다.
awk 'BEGIN {
# action=0: uncomment
# action=1: comment
action=0
in_optional_code_block=0
}
{
if ($0 ~ /^# BEGIN/) {
in_optional_code_block=1
} else if ($0 ~ /^# END/) {
in_optional_code_block=0
} else if (in_optional_code_block) {
if (action) {
if ($0 !~ /^#/) {
$0 = "# " $0
}
} else {
if ($0 ~ /^#/) {
sub(/^# ?/, "")
}
}
}
}
1'
나는 또한 그것과 함께 제공되는 작은 쉘 스크립트를 작성했습니다:
#!/usr/bin/env sh
syntax_error() {
echo "Usage: `basename \"$0\"` [comment|uncomment] file" >&2
exit 1
}
case "$1" in
0|uncomment) action=0; ;;
1|comment) action=1; ;;
*) syntax_error; ;;
esac
shift
if [ -z "$@" ]; then syntax_error; fi
awk 'BEGIN {
action='$action'
in_optional_code_block=0
}
{
if ($0 ~ /^# BEGIN/) {
in_optional_code_block=1
} else if ($0 ~ /^# END/) {
in_optional_code_block=0
} else if (in_optional_code_block) {
if (action) {
if ($0 !~ /^#/) {
$0 = "# " $0
}
} else {
if ($0 ~ /^#/) {
sub(/^# ?/, "")
}
}
}
}
1' "$@" > "[email protected]"
if [ $? -eq 0 ]; then mv "[email protected]" "$@"; fi
(GNU Awk 4.1.0 이상이면 구조를 이동하는 대신 마지막에 -i 플래그를 사용할 수 있습니다.)
답변2
질문의 "가능한 솔루션"을 해결하면 제안된 코드에 몇 가지 문제가 있습니다.
- 루프는
for (var in a)
인덱스를 순서대로 반복한다고 보장되지 않으므로a
주석 처리된 행이 잠재적으로 무작위 순서로 출력될 수 있습니다. BEGIN
합계 행을 감지하는 데 사용하는 패턴은END
두 행에 사용된 레이블을 쌍으로 연결하려고 시도하지 않으므로# BEGIN FOO
로 끝날 수 있습니다# END BAR
./^# /
블록 사이에 불필요한 코드 중복이 있습니다!/^# /
.- 빈 블록이
END
불필요하게 존재합니다. - 코드의 주석 처리가 해제되지 않았습니다.
주석의 영향을 받는 섹션에서 주석 처리된 줄의 주석 처리를 쉽게 해제할 수 있도록 #
열기 및 닫기 표시 줄에 추가 문자도 추가했습니다.
sed '/^# BEGIN SOMENAME$/,/^# END SOMENAME$/ s/^/#/' file
이렇게 하면 #
해당 표시 줄을 포함하여 와 줄 사이의 모든 줄 시작 부분에 문자가 삽입됩니다.# BEGIN SOMENAME
# END SOMENAME
특정 텍스트에 대해 다음과 같은 결과가 발생합니다.
code statement1
code statement2
## BEGIN SOMENAME
#some code
#some other code
## END SOMENAME
code statement n +1
code statement n +1
해당 문자가 아직 첫 번째 문자가 아닌 줄에만 삽입하는 경우 #
표시된 줄 사이에 원래 권장되는 줄에 대한 기록이 없기 때문에 반전 작업이 매우 어렵습니다.
주석을 해제하려면:
sed '/^## BEGIN SOMENAME$/,/^## END SOMENAME$/ s/#//' file
이는 첫 번째 명령에서 권장되는 줄에만 영향을 미치며 sed
각 줄의 시작 부분에 삽입된 문자를 제거하여 원래 상태로 되돌립니다.#
#
공백 문자와 그 뒤에 오는 문자를 사용하여 줄을 주석 처리 하고 싶습니다 .
sed '/^# BEGIN SOMENAME$/,/^# END SOMENAME$/ s/^/# /' file
댓글을 게시하기 위해
sed '/^# # BEGIN SOMENAME$/,/^# # END SOMENAME$/ s/# //' file
댓글을 취소하는데 사용됩니다.
awk
대신 동등한 작업을 사용하십시오 sed
.
의견:
awk '$0 == "# BEGIN SOMENAME", $0 == "# END SOMENAME" { $0 = "#" $0 }; 1' file
댓글을 취소하려면:
awk '$0 == "## BEGIN SOMENAME", $0 == "## END SOMENAME" { $0 = substr($0, 2) }; 1' file
두 명령 모두 정규식 대신 문자열 비교를 사용합니다. 왜냐하면 정규식은 일반적으로 더 빠르고 패턴 일치가 필요하지 않기 때문입니다. 주석 해제를 위한 두 번째 명령 호출은 substr()
입력 문자열에서 첫 번째 문자를 뺀 값을 반환합니다. 후행만으로 1
현재 행이 출력됩니다.