För närvarande har jag filer som innehåller avsnitt så här
code statement1 code statement2 # BEGIN SOMENAME some code some other code # END SOMENAME code statement n +1 code statement n +1
Vad jag vill göra är att kommentera vad som är mellan ”# BEGIN SOMENAME” och ”# END”, så att det i slutändan ser ut så här
code statement1 code statement2 # BEGIN SOMENAME # some code # some other code # END SOMENAME code statement n +1 code statement n +1
Kan jag uppnå detta med awk eller sed? och kan jag vända det enkelt ?, så bara en operation, som ”kommenterar” igen?
Vad jag vill undvika för att göra misstag, så om raderna redan har kommenterats ska det vara i fred. Även i ”kommentera in” bör det inte försöka göra något om raderna mellan slut och börja inte börjar med ett ”#”.
Försökte det nu i flera timmar, ingen framgång.
Hittade en möjlig lösning:
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
Kommentarer
- kanske, för den här gamla koden har misstag som att flera startrader (kopiera / klistra in buggar …?) efter den andra, och du behöver bara ignorera den första eller någon gång börjar början och filen slutar …. i ' hellre inte posta detta manus, det är konkurrensbruten nu ….
- du har rätt. lade till detta till utmaningar. Ursäkta blev trött, och det verkar alltid när jag hittade en partiell lösning, alla andra saker slutar fungera
Svar
Det här skriptet fungerar för mig. Jag testade det i GNU Awk 4.0.1, men borde också fungera i 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"
Jag skrev också ett litet medföljande skalskript:
#!/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
(Om du har GNU Awk 4.1.0 eller senare kan du använda flaggan -i istället för flyttkonstruktionen i slutet.)
Kommentarer
- @Mandragor Om SOMENAME i de inledande och avslutande kommentarerna måste matcha, ge mig ett rop.