Unix: Adicione nomes exclusivos depois dos sinais no texto

3

Eu tenho um arquivo parecido com o seguinte:

abcdefghijklmnopqrst
//
abcdefghijklmnopqrst
//
abcdefghijklmnopqrst

Eu uso o seguinte código para inserir uma linha com // até o início do documento (como é recomendado aqui: Adicionando texto ao início do arquivo de texto ), e salve esta atualização em um novo arquivo.

sed '1s/^/\/\/\'$'\n/' File_1.txt > File_2.txt

O que eu gostaria de fazer, no entanto, é adicionar nomes exclusivos após cada //, obtendo um resultado como este:

// Text 1
abcdefghijklmnopqrst
// Text 2
abcdefghijklmnopqrst
// Text 3
abcdefghijklmnopqrst

etc.

Eu estava pensando que eu poderia usar tr para traduzir por exemplo. "//" em "// Texto 1". Mas como adiciono o Texto 2 ao próximo //, texto 3 ao terceiro // etc.?  O arquivo txt é feito em mac-osx.

ATUALIZAÇÃO:

Sua solução parece boa, @PM 2Ring, no entanto, eu tenho o problema adicional, que o arquivo realmente se parece com isso:

// 
abcdefghijklmnopqrstu 
//            x   x 
abcdefghijklmnopqrstu 
//          x   x 
abcdefghijklmnopqrstu 

Assim, o nome é inserido perfeitamente na primeira linha, mas após o segundo par de /, o nome é inserido após x, no final da linha. Eu preciso inserir o nome logo após //, mas sem mudar o texto restante para a direita. É possível excluir a mesma quantidade de espaços, pois existem caracteres no nome? Isso não deve ser feito na primeira linha, é claro, pois suponho que isso excluiria os caracteres da segunda linha.

    
por Hjalte 28.01.2015 / 12:00

3 respostas

1

Você pode fazer isso facilmente com awk :

awk 'BEGIN{n=1}; /\/\//{$0=$0 " Text " n; n+=1}; {print}' infile

Se infile contiver

//
abcdefghijklmnopqrst
//
abcdefghijklmnopqrst
//
abcdefghijklmnopqrst

O comando acima imprime

// Text 1
abcdefghijklmnopqrst
// Text 2
abcdefghijklmnopqrst
// Text 3
abcdefghijklmnopqrst

O /\/\// de aparência críptica é um regex ( Reg ular Ex pression) contendo // . Em regexes awk são delimitados pela barra invertida / ; para colocar barras em um regex, você precisa escapar com a barra invertida \ .

No awk, padrão { ação } diz executar ação se a linha atual corresponder ao padrão . O padrão BEGIN é um padrão especial para indicar as ações que queremos que aconteçam antes que as linhas sejam lidas. Se não especificarmos um padrão, a ação será executada para todas as linhas (embora haja uma maneira de sobrescrever isso).

Esta versão atualizada funcionará em seu novo arquivo de entrada, mas infelizmente não preservará o espaçamento

awk 'BEGIN{n=1}; /^\/\//{$1=$1 " Text " n; n+=1}; {print}' infile

entrada

// x  x
abcdefghijklmnopqrst
//    x    x
abcdefghijklmnopqrst
//          x   x
abcdefghijklmnopqrst

saída

// Text 1 x x
abcdefghijklmnopqrst
// Text 2 x x
abcdefghijklmnopqrst
// Text 3 x x
abcdefghijklmnopqrst
    
por 28.01.2015 / 12:09
1

Você pode usar perl e o sinalizador de avaliação para incrementar uma variável na peça de substituição. Ele procura por todas as linhas que começam com // e anexa Text seguido por um número:

perl -pe 's{\A(//)}{$1 . " Text " . ++$i}e' File_1.txt

Produz:

// Text 1 
abcdefghijklmnopqrst
// Text 2 
abcdefghijklmnopqrst
// Text 3  
abcdefghijklmnopqrst

Atualizar (ver comentários):

Faça o agrupamento nos espaços após // e calcule o número de espaços a inserir na peça de substituição, como:

perl -pe 's{\A(//)(\h*)}{$1 . " Text " . ++$i . " " x ((length ($2)) - length(" Text " . $i))}e' temp

Usando seu último exemplo, ele gera:

// Text 1
abcdefghijklmnopqrstu 
// Text 2     x   x 
abcdefghijklmnopqrstu 
// Text 3   x   x
abcdefghijklmnopqrstu
    
por 28.01.2015 / 12:07
0

Convertendo a solução @Birei para a atualização de "problemas adicionais":

perl -pe 's{^// {10}}{sprintf("// Text %-3d ",++$i)}e  or
          s{^//     }{sprintf("// Text %d",   ++$i)}ex '          infile
    
por 28.01.2015 / 14:26