Esclarecimento: Usando GNU sed.
Status quo - ~/.screenrc, últimas linhas:
# name synthpop
# screen -t script emacs -nw /home/$USER/bin/synthpop
# name thrashmetal
# screen -t script emacs -nw /home/$USER/bin/thrashmetal
# number 1
# split -v
# focus
# chdir "/home/$USER/thrashmetal/src"
# screen -t scr watch nl asdkjlek.html
# number 2
# focus
# split
# focus
# screen -t output watch thrashmetal asdkjlek.html
# number 3
# focus
# split
# focus
# chdir "/home/$USER/thrashmetal/plan"
# screen -t soll watch less soll
# number 4
# focus
# name darkwave
# screen -t script emacs -nw /home/$USER/bin/darkwave
Mirar:
# name synthpop
# screen -t script emacs -nw /home/$USER/bin/synthpop
name thrashmetal
screen -t script emacs -nw /home/$USER/bin/thrashmetal
number 1
split -v
focus
chdir "/home/$USER/thrashmetal/src"
screen -t scr watch nl asdkjlek.html
number 2
focus
split
focus
screen -t output watch thrashmetal asdkjlek.html
number 3
focus
split
focus
chdir "/home/$USER/thrashmetal/plan"
screen -t soll watch less soll
number 4
focus
# name darkwave
# screen -t script emacs -nw /home/$USER/bin/darkwave
Minha tentativa atual, que quase dá conta do recado, mas falha ao parar assim que a linha chega, que é apenas uma nova linha sem nenhum sinal de comentário ou caracteres alfanuméricos:
sed 's+^# \(name thrashmetal\)+\1+;:a;s+# ++;ta' .screenrc
Explicação, intenção:
'
início de uma sequência de coisas para fazers
substituir+
use "+" como delimitador# …
percorra linha por linha até encontrar uma linha começando com "# "…\(
iniciar grupo para referência posterior posteriorname thrashmetal
e continuando com "nome thrashmetal"\)
fim do grupo+\1+
substitua a primeira correspondência dentro dessa linha apenas pela parte do grupo, sem o "#";
então, a partir daí, faça outra coisa…:a
faça um loop chamado "a";s
onde para cada linha seguinte, linha por linha, você substitui…+
defina "+" como delimitador#
a primeira correspondência de "#" dentro desta linha, independentemente do que o segue dentro desta linha…++
sem nada, excluindo-o efetivamente;ta
faça isso desde que você falhe, o que deve acontecer assim que você chegar ao final do parágrafo e, em seguida, as 2 novas linhas que separam o bloco thrashmetal do bloco darkwave e, em seguida, volte para onde "a" estava'
fim de uma sequência de coisas para fazer.screenrc
faça a referida sequência de coisas em relação ao arquivo ".screenrc" em meu diretório atual - meu diretório inicial
Saída padrão:
# name synthpop
# screen -t script emacs -nw /home/$USER/bin/synthpop
name thrashmetal
screen -t script emacs -nw /home/$USER/bin/thrashmetal
number 1
split -v
focus
chdir "/home/$USER/thrashmetal/src"
screen -t scr watch nl asdkjlek.html
number 2
focus
split
focus
screen -t output watch thrashmetal asdkjlek.html
number 3
focus
split
focus
chdir "/home/$USER/thrashmetal/plan"
screen -t soll watch less soll
number 4
focus
name darkwave
screen -t script emacs -nw /home/$USER/bin/darkwave
Como consertar isto? O que estou fazendo de errado para que o loop não pare assim que chega ao final do parágrafo thrashmetal, mas simplesmente salte para o próximo parágrafo - o parágrafo darkwave - e continue?
Qualquer coisa nesse loop deve estar errada, eu acho... Talvez o "t", mas "T" ou "b" também não funcionem...
Isso aplica uma substituição que exclui um caractere de espaço inicial
#
e um caractere de espaço subsequente de cada linha em um intervalo.O intervalo começa com a correspondência de linha
^# name thrashmetal$
e termina com a primeira correspondência de linha subsequente^$
(linha vazia).Ou, traduzido diretamente para
awk
:Aqui, o final
1
é a abreviação de{ print $0 }
ou{ print }
e faz com que a linha atual (possivelmente modificada) seja exibida (esta impressão do texto está implícita nosed
script).Para qualquer pessoa interessada no
ed
editor, você resolveria isso com o seguinte comando de edição:Isso move o cursor para a primeira linha do parágrafo desejado e aplica a substituição a essa linha e a todas as linhas posteriores até chegarmos a uma linha vazia.
Não podemos usar
... já que os endereços são calculados em relação à linha atual, e a linha atual está no final do arquivo quando iniciamos o editor. Como estamos no final do arquivo, o intervalo no comando seria inválido, pois o
/^$/
endereço seria uma linha anterior ao endereço inicial (em relação à linha atual, a primeira linha vazia vem antes do início do nosso parágrafo) .Sua própria abordagem, corrigida (com os delimitadores alterados para o padrão de pontos positivos e divididos em múltiplas expressões, o que é mais portátil):
Em vez de uma substituição inicial, deixo a correspondência da linha inicial do parágrafo determinar se o restante do script de edição será ignorado ou não. Ele será ignorado
b
se a linha não for encontrada.Se a linha for encontrada, nós a modificamos e criamos nosso rótulo
a
. Em seguida, imprimimos o buffer atual e substituímos seu conteúdo pela próxima linha usandon
. O loop continua como antes, removendo a#
substring e retornando ao rótulo se o conteúdo do buffer mudar.O principal problema com sua tentativa original,
... é que o "
a
-loop" é incondicional e, portanto, se aplica a cada linha da entrada, independentemente de a substituição inicial ter sido bem-sucedida ou falhar (você mostra as duas primeiras linhas como não sendo afetadas pelo seu comando, mas eu acho que isso é um erro de copiar e colar). O loop também não lerá a próxima linha, portanto só será executado uma vez em cada linha (a menos que várias#
substrings sejam encontradas em uma linha).Minha correção envolve dividir sua substituição inicial em um teste e uma substituição e, em seguida, garantir que o "
a
-loop" leia a próxima linha de entrada até que a substituição falhe. Também não substituirei#
strings múltiplas ou incorporadas (internas) em qualquer linha, apenas a primeira no início da linha.Este script parece fazer o que você deseja:
Estamos efetivamente dividindo as coisas em pedaços delimitados por linhas em branco. Quando encontramos um pedaço que começa com
# name thrashmetal
, removemos todas as#
strings do início das linhas.Dada a sua entrada de amostra, isso produz como saída:
O script sed com comentários:
Você também pode considerar usar o awk:
Aqui, ao definir RS (separador de registro de entrada) como em branco, você lida com os parágrafos como se fossem linhas únicas.
Usando qualquer awk: