Se as linhas comentadas existentes formarem um único bloco contíguo, você poderá corresponder a partir da primeira linha comentada, comentando apenas as linhas até e incluindo seu padrão final que ainda não foram comentadas
sed '/^#/,/dotan/ s/^[^#]/#&/' file
Se os comentários existentes não forem contíguos, devido à natureza gananciosa da correspondência sed, acho que você precisaria fazer algo como
tac file | sed '/dotan/,/^#/ s/^[^#]/#&/' | tac
ou seja, faça a correspondência ascendente do padrão final ao primeiro comentário - obviamente isso não é tão conveniente se você quiser uma solução no local.
Você pode manipular os dois casos (linhas comentadas em um único bloco contíguo ou intercaladas entre linhas não comentadas) com uma única sedchamada:
sed '1,/PATTERN/{/^#/{x;1d;b};//!{H;/PATTERN/!{1h;d};//{x;s/\n/&#/g}}}' infile
Isso processa apenas as linhas no 1,/PATTERN/intervalo. É um e xalterações manter espaço w. padrão de espaço toda vez que uma linha é comentada (para que nunca haja mais de uma linha comentada no buffer de espera) e anexa todas as linhas que não são comentadas ao Hespaço antigo (quando na 1ª linha 1de , respectivamente, 1htambém são necessárias para remover a inicial linha vazia no buffer de espera).
Quando atinge a linha correspondente a PATTERN, também o anexa ao Hbuffer antigo, e xaltera os buffers e substitui cada \ncaractere de linha ew no espaço do padrão por um \newline e a #(ou seja, todas as linhas no espaço do padrão começam agora com #, incluindo a primeira linha como a primeira linha no espaço de espera é sempre uma linha comentada).
Com uma amostra infile:
alice
#bob
bill
#charlie
ding
dong
dotan
jimmy
#garry
corrida:
sed '1,/dotan/{ # if line is in this range -start c1
/^#/{ # if line is commented -start c2
x # exchage hold space w. pattern space
1d # if 1st line, delete pattern space
b # branch to end of script
} # -end c2
//!{ # if line is not commented -start c3
H # append to hold space
/dotan/!{ # if line doesn't match dotan -start c4
1h # if 1st line, overwrite hold space
d # delete pattern space
} # -end c4
//{ # if line matches dotan -start c5
x # exchage hold space w. pattern space
s/\n/&#/g # add # after each newline character
} # -end c5
} # -end c3
}' infile # -end c1
saídas:
alice
#bob
bill
#charlie
#ding
#dong
#dotan
jimmy
#garry
portanto, está comentando apenas linhas de (e excluindo) #charlieaté (e incluindo) dotane deixando as outras linhas intocadas.
Claro, isso pressupõe que sempre haja pelo menos uma linha comentada antes da correspondência da linha PATTERN. Se não for esse o caso, você poderá adicionar uma verificação adicional antes da substituição:/^#/{s/\n/&#/g}
Isso faz o que você pede. Ele simplesmente funciona em uma pilha - construindo-a quando necessário e pelo tempo necessário entre ocorrências de linhas comentadas e descartando o buffer antigo em favor da nova linha comentada mais adiante na entrada quando encontrar uma. Cenário...
Desculpe, não sei por que fiz isso. Mas isso veio à mente.
De qualquer forma, sedespalha seus buffers entre cada última linha comentada de qualquer série, nunca retendo um único mais em seu buffer do que o necessário para rastrear com precisão a última ocorrência comentada e, a qualquer momento, encontra a última linha ao fazê-lo. A ginstrução final de execução tglobal e a ramificação são o buffer inteiro a ser impresso, caso contrário, ele criará Ptodas as linhas que liberar do buffer assim que o fizer.
Acho que foi isso que trouxe os acordeões à mente ...
printf %s\\n \#alice \#bob charlie dotan eric \
\#alice \#bob charlie dotan eric \
\#alice \#bob charlie dotan eric |
sed -e:n -e'l;/\n#.*\ndotan/!{$!{N;/^#/bn' \
-eb -e\} -e'/^#/s/\(\n\)\(dotan.*\)*/\1#\2/g' \
-et -e\} -eP\;D
#alice
#alice\n#bob$
#alice\n#bob\ncharlie$
#alice\n#bob\ncharlie\ndotan$
#alice
#bob\ncharlie\ndotan$
#bob\ncharlie\ndotan\neric$
#bob\ncharlie\ndotan\neric\n#alice$
#bob\ncharlie\ndotan\neric\n#alice\n#bob$
#bob\ncharlie\ndotan\neric\n#alice\n#bob\ncharlie$
#bob\ncharlie\ndotan\neric\n#alice\n#bob\ncharlie\ndotan$
#bob
charlie\ndotan\neric\n#alice\n#bob\ncharlie\ndotan$
charlie
dotan\neric\n#alice\n#bob\ncharlie\ndotan$
dotan
eric\n#alice\n#bob\ncharlie\ndotan$
eric
#alice\n#bob\ncharlie\ndotan$
#alice
#bob\ncharlie\ndotan$
#bob\ncharlie\ndotan\neric$
#bob\ncharlie\ndotan\neric\n#alice$
#bob\ncharlie\ndotan\neric\n#alice\n#bob$
#bob\ncharlie\ndotan\neric\n#alice\n#bob\ncharlie$
#bob\ncharlie\ndotan\neric\n#alice\n#bob\ncharlie\ndotan$
#bob
charlie\ndotan\neric\n#alice\n#bob\ncharlie\ndotan$
charlie
dotan\neric\n#alice\n#bob\ncharlie\ndotan$
dotan
eric\n#alice\n#bob\ncharlie\ndotan$
eric
#alice\n#bob\ncharlie\ndotan$
#alice
#bob\ncharlie\ndotan$
#bob\ncharlie\ndotan\neric$
#bob
#charlie
#dotan
eric
Há apenas uma diferença entre este comando e o acima e esse é o lcomando ook no topo. Quando nós look em sed's espaço de padrões como ele funciona, podemos ter uma melhor idéia do que se passa nos bastidores e uma melhor compreensão de como direcionar seus esforços.
Nesse caso, podemos observar a sedentrada da pilha até encontrar uma segunda ocorrência de \n#.*\ndotanentrada, e quando ela começa a imprimir a linha anterior por vez. É meio legal. Eu aprendi muito trabalhando nisso.
Muito bom, obrigado! O parágrafo final com explicações é fantástico, também passarei algum tempo aprendendo com este post. Nice stack!
13135 dotancohen
1
@ Dotancohen - esta foi uma pergunta muito boa. Dê uma olhada na edição para ver a pilha .
mikeserv
2
Percebo no histórico de edição a entrada Handle many dotans. Tenho certeza de que este é o pior pesadelo da minha esposa.
13135 dotarkhen
1
@dotancohen - sim, esta foi uma pergunta difícil. Coisas como #\ndotan\ndotané difícil para essas coisas. Eu falo sério quando digo que é uma boa pergunta. Eu acho que eu consegui quase perfeito, mas um problema que poderia correr em é se seus blocos de comentário estão separados por 1000 linhas - que irá retardá-lo. Você pode colocar algo como s/\n/&/150;tantes da primeira /\n#coisa a quebrar o buffer se ele se estender por 150 linhas, por exemplo. E de qualquer maneira, talvez seja exatamente o que ela estava esperando o tempo todo !
Aqui está outro
sed
:Isso faz o que você pede. Ele simplesmente funciona em uma pilha - construindo-a quando necessário e pelo tempo necessário entre ocorrências de linhas comentadas e descartando o buffer antigo em favor da nova linha comentada mais adiante na entrada quando encontrar uma. Cenário...
Desculpe, não sei por que fiz isso. Mas isso veio à mente.
De qualquer forma,
sed
espalha seus buffers entre cada última linha comentada de qualquer série, nunca retendo um único mais em seu buffer do que o necessário para rastrear com precisão a última ocorrência comentada e, a qualquer momento, encontra a última linha ao fazê-lo. Ag
instrução final de execuçãot
global e a ramificação são o buffer inteiro a ser impresso, caso contrário, ele criaráP
todas as linhas que liberar do buffer assim que o fizer.Acho que foi isso que trouxe os acordeões à mente ...
Há apenas uma diferença entre este comando e o acima e esse é o
l
comando ook no topo. Quando nósl
ook emsed
's espaço de padrões como ele funciona, podemos ter uma melhor idéia do que se passa nos bastidores e uma melhor compreensão de como direcionar seus esforços.Nesse caso, podemos observar a
sed
entrada da pilha até encontrar uma segunda ocorrência de\n#.*\ndotan
entrada, e quando ela começa a imprimir a linha anterior por vez. É meio legal. Eu aprendi muito trabalhando nisso.fonte
Handle many dotans
. Tenho certeza de que este é o pior pesadelo da minha esposa.#\ndotan\ndotan
é difícil para essas coisas. Eu falo sério quando digo que é uma boa pergunta. Eu acho que eu consegui quase perfeito, mas um problema que poderia correr em é se seus blocos de comentário estão separados por 1000 linhas - que irá retardá-lo. Você pode colocar algo comos/\n/&/150;t
antes da primeira/\n#
coisa a quebrar o buffer se ele se estender por 150 linhas, por exemplo. E de qualquer maneira, talvez seja exatamente o que ela estava esperando o tempo todo !