Como substituir um padrão atípico em um arquivo de texto usando sed

1

Eu tenho um arquivo de configuração MRTG contendo linhas começando com a palavra "Target". Agora, em tais linhas, há um padrão começando com o caractere "#" e terminando com o caractere ":".

Uma linha de amostra pode ter essa aparência (observe dois tipos, mas os marcadores de início / fim ainda são os mesmos):

   Target[192.168.0.1_Gi1_1]: #Gi1/1:[email protected]:::::2

   Target[192.168.0.1_Gi1_31]: #Gi1/31:[email protected]:::::2

O que eu preciso é que o sed encontre essas linhas e substitua o padrão "#Gix/n:" por "ifInErrors#Gix/n&ifInErrors#Gix/n:" , onde x = 1-9 , n = 1-48 .

Assim, as duas linhas de amostra mostradas acima seriam modificadas para estas:

Target[192.168.0.1_Gi1_1]: ifInErrors#Gi1/1&ifInErrors#Gi1/1:[email protected]:::::2

Target[192.168.0.1_Gi1_31]: ifInErrors#Gi1/31&ifInErrors#Gi1/31:[email protected]:::::2
    
por Sankung 23.01.2013 / 16:00

2 respostas

1

O que você precisa é de um grupo de captura - você captura o que precisa entre parênteses e pode referenciá-lo na substituição. Assim:

 grep ^[[:space:]]*Target file | sed 's/\(#Gi[1-9]\/[1-9][0-9]*\):/ifInErrors\&ifInErrors:/'
    
por Drake Clarris 23.01.2013 / 16:41
1
sed '/Target/s/\(#Gi[0-9]*_[0-9]*:\)/ifInErrors\&ifInErrors/' input.txt

sed '/Target/ é equivalente a grep Target | sed , exceto que envolve menos um processo & amp; um tubo a menos.

s/ significa 'substituição', o comando sed mais comum; s/foo/bar/ substitui instâncias da string foo por bar , por exemplo.

/\(#Gi[0-9]*\/[0-9]*:\) ... os colchetes (que precisam ser escapados com \ ) dizem ao sed para marcar tudo entre eles como (ou \ 2 para o segundo padrão marcado, \ 3 para o terceiro etc. ). [0-9]* significa 'qualquer número de números' e \/ é um escape / (ele precisa ser de escape porque estou usando / como o separador para sed; se você usar outro separador, como | , então você não precisaria escapar do /). Então, #Gi[0-9]*\/[0-9]*: é um padrão que significa 'comece com #, seguido por Gi, depois qualquer número de números, então /, então qualquer número de números, terminando com:'.

Então, corresponde a qualquer string detectada pelo padrão #Gi[0-9]*\/[0-9]*: Na primeira string dada na pergunta,

Target[192.168.0.1_Gi1_1]: #Gi1/1:[email protected]:::::2
##  The pattern #Gi[0-9]*\/[0-9]*: will match the substring
#Gi1/1:

... portanto, /ifInErrors\&ifInErrors/ informa ao sed 'substituir #Gi1/1: por ifInErrors#Gi1/1:&ifInErrors#Gi1/1: '.

Algumas coisas extras: se você quiser apenas imprimir as linhas que começam com 'Target', fazendo a substituição do sed, você pode usar esta linha:

sed -n '/Target/s/\(#Gi[0-9]*\/[0-9]*:\)/ifInErrors\&ifInErrors/p'

-n diz ao sed 'não imprime a saída', e o p no final diz para imprimir as linhas em que o sed está trabalhando.

Se você quisesse sobrescrever seu arquivo original, você usaria isso:

sed -i '/Target/s/\(#Gi[0-9]*\/[0-9]*:\)/ifInErrors\&ifInErrors/'
    
por evilsoup 31.01.2013 / 05:20