Atualmente, tenho arquivos que contêm seções como esta
code statement1 code statement2 # BEGIN SOMENAME some code some other code # END SOMENAME code statement n +1 code statement n +1
O que eu quero fazer é comentar o que está entre “# BEGIN SOMENAME” e “# END”, para que no final fique assim
code statement1 code statement2 # BEGIN SOMENAME # some code # some other code # END SOMENAME code statement n +1 code statement n +1
Posso fazer isso com awk ou sed? e posso reverter isso facilmente? Apenas uma operação, que “comenta” novamente?
O que eu quero evitar é cometer erros, então se as linhas já estão comentadas deve ser deixado sozinho. Também em “comentar em”, não deve tentar fazer algo se as linhas entre o fim e o início não começam com um “#”.
Tentei isso agora por várias horas, sem sucesso.
Encontrou uma solução possível:
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
Comentários
- talvez, porque este código antigo tem erros como essas várias linhas de início (copiar / colar bugs …?) depois da outra, e você só precisa ignorar o primeiro ou às vezes o início começa e o arquivo termina …. i ' prefiro não postar este script, ele está completamente quebrado agora ….
- você está certo. adicionou isso aos desafios. Desculpe, cansei, e parece que sempre que encontro uma solução parcial, todas as outras coisas param de funcionar
Resposta
Este script funciona para mim. Eu testei no GNU Awk 4.0.1, mas deve funcionar no Nawk também.
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"
Eu também escrevi um pequeno script de shell de acompanhamento:
#!/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
(Se você tiver GNU Awk 4.1.0 ou posterior, você pode usar o sinalizador -i em vez da construção de movimento no final.)
Comentários
- @Mandragor Se SOMENAME nos comentários de abertura e fechamento tiver que corresponder, avise-me.