combina xargs com sed para modificar ou alterar um arquivo

0

Estou pesquisando o padrão geral *** _ 23 no final de uma linha (mas não: at_23) dentro de um arquivo, e estou tentando alterar todas essas descobertas para \ < 23 & gt ;, na mesmo arquivo de origem (a função de inserção é sed -i)
Eu estou fazendo:

egrep '[b-s u v w x y z ]+_[0-9]+$' sst_piso_top_c0.spf_typ_C | xargs...

mas toda a minha tentativa de continuar com o sed falhou.

Alguém pode explicar como continuar após os xargs? Como devo entregar uma lista no sed e dizer ao sed para processar cada um na lista, e alterá-lo, no mesmo arquivo?

    
por meny 11.01.2016 / 08:12

3 respostas

0

Talvez eu não esteja entendendo o problema, mas você só precisa usar sed para isso:

$ sed -ri 's/[b-suvwxyz]+_([0-9]+)$/\<>/g' sst_piso_top_c0.spf_typ_C

Aqui estamos usando () para capturar esse valor e, em seguida, para imprimi-lo na seção de substituição.

    
por 11.01.2016 / 08:45
0

Não é necessário combinar egrep e sed , pois os dois comandos pesquisarão correspondências nos arquivos e exibirão os resultados ( egrep ) ou agirá com base neles ( sed ), portanto sed sozinho vai fazer. Mas, para entender por que sua linha não funcionou, vou com o seu exemplo:

A saída regular egrep tem o formato filename:matching_line quando executado em vários arquivos e matching_line quando executado em um único arquivo, enquanto sed espera apenas nomes de arquivos. Para suprimir a saída normal egrep e imprimir apenas os nomes dos arquivos que incluem correspondências, use a opção -l .

Além disso, você não quer um espaço na sua lista de caracteres ( [...] ), caso contrário, será muito ganancioso e combinará mais do que uma única palavra. Uma linha que funcionaria é:

$ egrep -l '[b-su-z]+_[0-9]+$' sst_piso_top_c0.spf_typ_C | xargs sed -ri 's/[b-su-z]+_([0-9])+$/\<>/g'

Se um comando composto não funcionar, geralmente é uma boa ideia executar as partes separadas por conta própria e verificar seus resultados. Além disso, mensagens de erro como "Nenhum arquivo desse tipo" geralmente apontam na direção certa (e seria uma boa ideia incluí-las no relatório aqui).

Por fim, como dito acima, combinar egrep e sed não faz sentido. Uma linha sensata seria

$ sed -ri 's/[b-su-z]+_([0-9])+$/\<>/g' sst_piso_top_c0.spf_typ_C

Atualização: houve um erro de digitação no meu regex, que eu corrigi. Eu também incluí a backreference para os números na partida que foi originalmente incluída por zuazo. Parece mais claro a partir dos comentários que você escreveu agora que não quer substituir a correspondência completa por uma expressão estática \<23> como compreendi inicialmente, mas deseja que o número correspondente apareça entre colchetes angulares ...

    
por 11.01.2016 / 09:21
0

Ok, para atender aos requisitos que você esclareceu nos comentários abaixo da sua pergunta, eu dividiria as coisas em duas partes:

  1. exclui todas as linhas que leem at_ logo antes do número final
  2. das linhas restantes, remova o sublinhado no final e coloque o número entre colchetes angulares precedido por uma barra invertida.

Solução para a parte 1:

Isso é feito com mais facilidade escrevendo-se uma expressão regular que corresponda exatamente ao que não deseja e, em seguida, informando ao comando de chamada a saída apenas das linhas que não partida. Isso é mais facilmente feito com grep , então vamos usá-lo:

egrep -v "at_[0-9]+" sst_piso_top_c0.spf_typ_C

A opção -v ou --invert-match informa grep para imprimir somente linhas não correspondentes.

Solução para a parte 2:

Isso é mais facilmente feito com sed s (ubstitute) -command:

sed -r 's/_([0-9]+)$/\<\>/g'

a expressão regular corresponde a sublinhado e um número no final da linha. Ao colocar a parte numérica entre parênteses (...) , podemos colá-la com na seção de substituição. As seções de substituição completas consistem de colchetes angulares invertidos, incluindo nossa referência de referência \<\> . A barra invertida precisa ser escapada com outra barra invertida \ , porque é tratada como um caractere de escape especial.

Juntando tudo:

Se canalizarmos a saída do comando egrep em 1. para o nosso comando sed de 2., os comandos sed usarão como fluxo de entrada:

egrep -v "at_[0-9]+" sst_piso_top_c0.spf_typ_C | sed -r 's/_([0-9]+)$/\<\>/g' > sst_piso_top_c0.spf_typ_C.new

Normalmente, os resultados de sed seriam enviados para a saída padrão, portanto, a linha acima os redireciona para um arquivo ( > newfile ). Note que este nome de arquivo tem que ser diferente do que o egrep está lendo, senão sobrescreveríamos o mesmo arquivo que estamos lendo e acabamos com um arquivo vazio.

    
por 11.01.2016 / 18:18

Tags