Eu tento descomentar linhas específicas de um arquivo com padrões no Oracle Linux 8.6 usando o bash. Há espaços em branco à esquerda em certas linhas onde os comentários não são removidos. Eu tentei descomentar as linhas comentadas com sed e grep para corresponder aos padrões. Eu preciso corresponder exatamente a dois números da saída. Há uma palavra por coluna (total de 2 colunas) no arquivo, cada uma com números.
Exemplo: coluna1:pd 19 _ORA coluna2:svg 38 .
Preciso descomentar linhas no local com correspondência exata de 19 e 38 sem 190, 1900 ou 019 etc. excluindo linhas como,
#pd19_ORA svg37
#pd199_ORA svg388
Código:
sed -n '/\<19\>/,+1p' cmfile|grep '38'|sed -i '/38/s/^#//g' cmfile
Conteúdo do arquivo:
#pd19_ORA svg38
#pd19_ORA sil38
#pd29_ORA sil37
A primeira linha ainda é comentada após usar sed com inplace, mas o comentário da segunda linha é removido.
Saída:
#pd19_ORA svg38
pd19_ORA sil38
#pd29_ORA sil37
Como remover o comentário da primeira linha que tem espaços em branco sem remover o espaço inicial?
Saída esperada:
pd19_ORA svg38
pd19_ORA sil38
#pd29_ORA sil37
Você pode tentar
awk
e comandar assim pode fazer o trabalho. Se você precisa ter as strings específicas19
e38
em lugares específicos você deve mencioná-las em questão:Este comando procura por linha com
19
e38
e remove o#
símbolo. E então imprime a linha (independentemente se é match e editada ou não)Se você quiser ter certeza de
#
que é o primeiro símbolo que não seja espaço em branco na linha, você pode modificar o script assim:Aqui está um script alterado que busca por strings específicas, reunindo os números desejados:
Acho que você está procurando remover um
#
caractere inicial de todas as linhas que contêm o número19
, mantendo qualquer espaço em branco inicialIsso procura por linhas que contenham
19
(mas sem dígitos em ambos os lados, como019
ou193
), pois não consegui\<19\>
encontrar nenhuma de suas linhas aqui.No caso em que você deseja linhas contendo
19
e38
precisa simplesmente estender a linha inicial correspondente:Em ambos os casos, para todas essas linhas correspondentes, capturamos qualquer espaço inicial que precede um
#
caractere para que possamos adicioná-lo de volta à saída.Finalmente, como mais uma variação,
sed -i ...
pode ser usado para atualizar o arquivo aparentemente no lugarSupondo que você queira descomentar as linhas que contêm 38 e que seguem uma linha que contém um delimitado por palavra¹,
19
como sua tentativa sugere, você pode querer fazer:Em seu:
O
sed -i '/38/s/^#//g' cmfile
comando não lê a entrada, ele apenas editacmfile
no local, removendo uma margem#
em qualquer linha que contenha38
(aliás, issog
é supérfluo, pois só pode haver uma substituição).Então isso
sed -n '/\<19\>/,+1p' cmfile|grep '38'
é inútil, pois nada está lendo sua saída.Observe também que todas as
-i
,+1
,\<\>
são extensões GNU não padrão², enquanto operl
comando funcionará em qualquer sistema³.Editar
Com seus requisitos atualizados, onde você deseja descomentar as linhas onde o primeiro campo contém 19 e o segundo contém 38 (elas mesmas não cercadas por outros dígitos):
Aqui, usando o
-a
modo wk, os campos são disponibilizados na@F
matriz ou, se houver espaço em branco em ambos os lados, o#
que resultaria no primeiro campo se tornando o segundo campo, faça a correspondência de linha completa com uma expressão regular:Onde temos (veja
perldoc perlrun
,perldoc perlop
eperldoc perlre
para detalhes):-p
:sed
modo, onde a-e
expressão é avaliada para cada linha de entrada.-i
:i
edição n-places/regexp/replacement/
:s
substitua a primeira correspondência da expressão regular porreplacement
.\s
: qualquer caractere de espaço em branco,\S
para caracteres não-brancos.<atom>*
: o átomo anterior repetido qualquer número de vezes, incluindo 0, tantas quantas possíveis\K
:K
eep o que está à esquerda, ou IOW redefine o início da partida que acabará sendo substituído.(?=...)
: visão positiva para o futuro, ou IOW "desde que o que se segue corresponda ..."(?<!...)
: look-behind negativo, ou IOW "desde que o que precede não corresponda ..."(?!...)
: visão negativa para o futuro\d
: qualquer caractere de dígito decimal. Sem-C
(para modo Unicode), isso é limitado a 0123456789.¹ Em qualquer caso, o
19
inpd19_ORA
não é delimitado por palavras, pois ambosd
e_
são caracteres de palavras; se você quiser corresponder a um on19
que não seja precedido nem seguido por um dígito decimal, você usaria(?<!\d)19(?!\d)
instead of\b19\b
(o equivalente em Perl deex
'\<19\>
).² Bem, estritamente falando,
\<\>
originou-se emex
/vi
, não no GNUsed
e-i
foi copiado pelo GNUsed
deperl
, e,+1
deed
.³ Embora você precise do perl 5.10.0 (de 2007) ou mais recente para
\K
(paraK
guardar o que está à esquerda dele). Em sistemas com uma versão mais antiga doperl
, você pode substituirs/^\s*\K#//
pors/^(\s*)#/$1/
.^#
corresponde apenas#
ao início da linha. Uma alternativa para permitir espaços em branco antes do comentário é^[ \t]*#
Então, essa linha deve funcionar: