Sed Substituir em um grupo específico de posições

1

Eu tenho um arquivo de entrada de amostra como abaixo:

Apple   Orange      Gold    Silver Spoon Apple  Orange              Gold    
Apple          
Apple   Orange 
Apple   Orange      
Mango               Gold    Silver Spoon Apple  Orange  

Eu preciso verificar se a 15ª a 20ª posição é Espaço e, em seguida, substituí-la por uma string Silver . Também preciso substituir completamente o conteúdo da 50ª para a 70ª posição com xxxxxxxxxxxxxxxxxxxxx

    
por Georgi 11.06.2015 / 06:22

3 respostas

0
sed 's/^\(.\{14\}\)      /Silver/
     s/^\(.\{49\}\).\{20\}/xxxxxxxxxxxxxxxxxxxxx/
'    <infile >outfile

Isso, eu acho.

    
por 11.06.2015 / 07:14
1

Dependendo de como linhas menores devem ser manipuladas (veja meu comentário acima), aqui está uma sed solution:

sed -e '/^.\{14\} \{6\}/s/^\(.\{14\}\) \{6\}/Silver/' \
    -e '/^.\{49\}./s/^\(.\{49\}\)\(.\{1,21\}\)\?\(.*\)\?/xxxxxxxxxxxxxxxxxxxxx/'

e muito melhor legível (e menos propenso a erros) GNU awk version:

awk '
  BEGIN { FIELDWIDTHS = "14 6 29 21 999" ; OFS = "" }
  $2 == "      " { $2 = "Silver" }
  $4 != ""       { $4 = "xxxxxxxxxxxxxxxxxxxxx" }
  { print }
'

Explicação:

1.) sed: O comando sed é construído por duas substituições independentes, a primeira lida com a caixa "Prata" e a segunda com a "xxx ...". As substituições sed são da forma:

/pattern/s/pattern2/replacement/

A respectiva substituição é executada se o primeiro padrão corresponder e, para essas linhas, o segundo padrão é substituído pela expressão de substituição. Os detalhes são as expressões codificadas sed típicas:

. - um caractere arbitrário

\{14\} - uma repetição da subexpressão precedente (aqui 14 vezes)

\(expr\) - uma subexpressão que pode ser referenciada na string de substituição por , , etc., onde o número real é definido pela n'ésima expressão parêntesis

\? - especifica que a subexpressão precedente é uma parte opcional

2.) awk: O programa awk executa a seção BEGIN uma vez, e as seções subseqüentes para cada linha do arquivo de dados, e a respectiva ação right {...} only se a condição da mão esquerda for verdadeira.

FIELDWIDTHS - especifica a largura dos campos de dados nas linhas de entrada, para que cada campo possa ser endereçado por $i (para algum campo i)

OFS="" - uma string vazia; os campos de saída não devem ter nenhuma separação adicional

$2 == " " - se o segundo campo (de acordo com a especificação FIELDWIDTHS ) contiver seis espaços em branco, substitua-o pela string especificada

$4 != "" - se o quarto campo contiver dados, substitua-o pela string "xxx ..."

{ print } - uma impressão incondicional da linha atual, que foi modificada por uma ou ambas as ações anteriores ou mostra a linha não modificada de outra forma

    
por 11.06.2015 / 07:16
0

Supondo que linhas contendo menos de 21 caracteres (para a primeira substituição) e que linhas contendo menos de 70 caracteres (para a segunda substituição) devem ser descartadas, usando Perl:

< inputfile perl -pe 's/^(.{14}) {6}/$1Silver/; s/^(.{49}).{21}/$1xxxxxxxxxxxxxxxxxxxxx/' > outputfile

Supondo que linhas contendo menos de 21 caracteres (para a primeira substituição) e que linhas contendo menos de 70 caracteres (para a segunda substituição) devem ser preenchidas com espaços primeiro, usando awk + Perl:

< inputfile awk '{printf "%-70s\n", $0}' | perl -pe 's/^(.{14}) {6}/$1Silver/; s/^(.{49}).{21}/$1xxxxxxxxxxxxxxxxxxxxx/' > outputfile

Resumo do comando # 1 :

  • < inputfile : redireciona o conteúdo de inputfile para perl ' stdin
  • -p : força o Perl a imprimir as linhas
  • -e : força o Perl a ler uma linha de programa dos argumentos
  • > outputfile : redireciona o conteúdo de perl stdout para outputfile

Divisão do comando # 2 :

  • < inputfile in awk : redireciona o conteúdo de inputfile para awk ' stdin
  • {printf "%-70s", $0} : preenche cada linha com espaços até que o número de caracteres na linha seja 70
  • | : pipes awk stdout to perl stdin
  • -p : força o Perl a imprimir as linhas
  • -e : força o Perl a ler uma linha de programa dos argumentos
  • > outputfile : redireciona o conteúdo de perl stdout para outputfile

Repartição da substituição # 1 :

  • s : afirma para executar uma substituição
  • / : inicia o padrão de pesquisa
  • ^ : corresponde ao início da linha
  • ( : inicia o grupo de captura
  • .{14} : corresponde a 14 ocorrências de qualquer caractere
  • ) : pára o grupo de captura
  • {6} : corresponde a 6 ocorrências de um caractere
  • / : interrompe o padrão de pesquisa / inicia o padrão de substituição
  • $1 : substitui pelo grupo capturado
  • Silver : adiciona uma Silver string
  • / : interrompe o padrão de substituição

Divisão da substituição # 2 :

  • s : afirma para executar uma substituição
  • / : inicia o padrão de pesquisa
  • ^ : corresponde ao início da linha
  • ( : inicia o grupo de captura
  • .{49} : corresponde a 49 ocorrências de qualquer caractere
  • ) : pára o grupo de captura
  • .{21} : corresponde a 21 ocorrências de qualquer caractere
  • / : interrompe o padrão de pesquisa / inicia o padrão de substituição
  • $1 : substitui pelo grupo capturado
  • xxxxxxxxxxxxxxxxxxxxx : adiciona uma xxxxxxxxxxxxxxxxxxxxx string
  • / : interrompe o padrão de substituição

Exemplo de saída:

:~/tmp$ cat inputfile
Apple   Orange      Gold    Silver Spoon Apple  Orange              Gold    
Apple          
Apple   Orange 
Apple   Orange      
Mango               Gold    Silver Spoon Apple  Orange  
~/tmp$ < inputfile perl -pe 's/^(.{14}) {6}/$1Silver/; s/^(.{49}).{21}/$1xxxxxxxxxxxxxxxxxxxxx/'
Apple   OrangeSilverGold    Silver Spoon Apple  Oxxxxxxxxxxxxxxxxxxxxxld    
Apple          
Apple   Orange 
Apple   OrangeSilver
Mango         SilverGold    Silver Spoon Apple  Orange  
~/tmp$ < inputfile awk '{printf "%-70s\n", $0}' | perl -pe 's/^(.{14}) {6}/$1Silver/; s/^(.{49}).{21}/$1xxxxxxxxxxxxxxxxxxxxx/'
Apple   OrangeSilverGold    Silver Spoon Apple  Oxxxxxxxxxxxxxxxxxxxxxld    
Apple         Silver                             xxxxxxxxxxxxxxxxxxxxx
Apple   OrangeSilver                             xxxxxxxxxxxxxxxxxxxxx
Apple   OrangeSilver                             xxxxxxxxxxxxxxxxxxxxx
Mango         SilverGold    Silver Spoon Apple  Oxxxxxxxxxxxxxxxxxxxxx
~/tmp$
    
por 11.06.2015 / 08:12