Adicionando uma linha ao início de um arquivo, com base em outras linhas no arquivo

2

Eu tenho arquivos com a seguinte estrutura:

foo.bar.baz () ->
  templateUrl: require('x.jade')

Eu preciso transformar esses arquivos de maneira que:

  1. Eles são prefixados com a linha var templateUrl = require('x.jade')
  2. A linha templateUrl: é substituída por templateUrl: templateUrl .

Como posso fazer isso? Uma opção é um script bash que, para cada arquivo:

  1. grep s para templateUrl: para obter a parte require .
  2. cat s a linha var templateUrl e o arquivo juntos em um novo arquivo e, em seguida, substitui o arquivo original.
  3. Usa sed para substituir templateUrl: require... por templateUrl .

Mas isso pode ser feito com um único script sed ou awk que pode ser executado para cada arquivo?

    
por user88974 01.08.2017 / 18:02

2 respostas

2

@ perl da solução de simlev realmente tem menos etapas, mas gostaria de apresentar meu comando sed . É mais relevante porque o OP já imaginou usar sed e solicita explicitamente um script sed ou awk .

sed -n '1h;:a;n;s/require/&/;tInsert;H;ba;:Insert;H;s/^/var/;s/:/ =/;G;s/: .*/: templateUrl/;p'

Observação: este comando não funcionará se o arquivo contiver mais de uma linha com : ou require .

Explicação:

sed -n        # -n option disables automatic printing.

1 h           # h command puts the first line (address 1) in the hold space,
              # replacing any previous content.

:a            # Set a mark with label 'a'.

n             # n command prints the pattern space and loads next line of input,
              # replacing all pattern space content.
              # But it will not print because of -n option.

s/require/&/  # Test if the pattern space has the line OP wants edit.

t Insert      # If substitution was made, t command jumps to the mark with label 'Insert'.

H             # If not, continue with H command, it appends a '\n' to the hold space content
              # and then appends the pattern space to the hold space.

b a           # b (branch) command, jumps to the mark with label 'a'.

:Insert       # Exit from the 'a' loop. Here the hold space has all the lines that precede
              # the line with 'replace', and pattern space has the line with 'replace'.
H             # The line with 'replace' is appended to the hold space too.

s/^/var/      # Here sed finally edits the line, replacing the beginning with 'var' ...

s/:/ =/       # and only the first ':' with ' ='.

G             # G command appends the content of hold space to the edited pattern space,
              # here that line edited above in pattern space becomes the first line.

s/: .*/: templateUrl/    # One more substitution.

p'            # Finally, print the pattern space.
    
por 03.08.2017 / 06:57
2

Arquivo (s) de entrada:

foo.bar.baz () ->
  templateUrl: require('x.jade')

comando perl :

perl -i -0777pe '$_=~s/templateUrl:( \K.*)/templateUrl/;print"var templateUrl =$1\n"' *

Arquivo (s) de saída:

var templateUrl = require('x.jade')
foo.bar.baz () ->
  templateUrl: templateUrl

Repartição:

  • perl linguagem de script que se destaca na manipulação de texto
  • -i editar arquivos no local
  • -0777 trabalha com o arquivo como um todo, ao contrário de linha por linha
  • p imprime o arquivo (nesse caso, o arquivo será salvo, devido à opção -i )
  • e executa o seguinte comando, ao contrário de executar o código salvo em um arquivo
  • ' início das instruções
  • $_=~s executa uma substituição no arquivo inteiro ( $_ )
  • /templateUrl:( \K.*))/ procura por uma linha que corresponda à regex templateUrl: .* e capture a string correspondente à subexpressão em parêntese  .* para uma variável (chamada $1 por padrão)
  • templateUrl/ substitui a peça após o marcador \K na linha correspondente ao texto templateUrl
  • ; separa entre instruções
  • print"var templateUrl =$1\n" print var templateUrl = , o conteúdo de $1 e uma nova linha
  • a essa altura, o restante do arquivo é implicitamente impresso, porque a opção p foi especificada
  • ' end of instructions
  • * processa todos os arquivos no diretório atual

Pode haver, claro, diferentes abordagens, como:

perl -i -ne 'if ($_=~s/templateUrl:( \K.*)/templateUrl/){$a="templateUrl =$1"} {$file.=$_} END{print"var $a\n$file"}' *

AWK :
Como a pergunta é sobre sed ou awk , vale a pena observar que qualquer abordagem pode ser implementada com a mesma facilidade em awk :

awk -i 'BEGIN {RS="
awk -i '/templateUrl: / {a="templateUrl = "$2;gsub("templateUrl: .*","templateUrl: templateUrl")} NR==1 {file=$0} NR==2{file=file"\n"$0} END{print a"\n"file}' *
"} {match($0,/templateUrl:( .*)/,m); gsub("templateUrl: .*","templateUrl: templateUrl"); print "var templateUrl ="m[1]$0}' *
foo.bar.baz () ->
  templateUrl: require('x.jade')
    
por 02.08.2017 / 12:26