Como substituir todas as strings em um arquivo que comece com algum prefixo

6

Exemplo:

1:20 2:25 3:0.432 2:-17 10:12

Desejo substituir todas as strings que começam por 2: to 2:0 .

Saída:

1:20 2:0 3:0.432 2:0 10:12
    
por Roy 13.05.2015 / 10:12

5 respostas

13

Usando sed :

sed -E 's/((^| )2:)[^ ]*//g' in > out

Além disso, conforme inspirado na resposta do souravc , se houver não a chance de um 2: substring após o início de uma string not contendo uma substring 2: inicial (por exemplo, existe não uma chance de uma string 1:202:25 , que a seguinte encurtada comando substituiria para 1:202:0 ), o comando pode ser encurtado para isto:

sed -E 's/2:[^ ]*/2:0/g' in > out

Resumo do Comando # 1 / # 2 :

  • -E : torna sed intepret o padrão como um padrão ERE (expressão regular estendida);
  • > out : redireciona stdout para out ;

% de falha do comandosed # 1 :

  • s : afirma para executar uma substituição
  • / : inicia o padrão
  • ( : inicia o grupo de captura
  • ( : inicia o agrupamento das strings permitidas
  • ^ : corresponde ao início da linha
  • | : separa a segunda string permitida
  • : corresponde a um caractere
  • ) : para de agrupar as strings permitidas
  • 2 : corresponde a um caractere 2
  • : : corresponde a um caractere :
  • ) : pára o grupo de captura
  • [^ ]* : corresponde a qualquer número de caracteres que não seja
  • / : interrompe o padrão / inicia a sequência de substituição
  • : backreference substituído pelo primeiro grupo de captura
  • 0 : adiciona um caractere 0
  • / : interrompe a sequência de substituição / inicia os sinalizadores de padrão
  • g : afirma para executar a substituição globalmente, ou seja, para substituir cada ocorrência do padrão na linha

% de falha do comandosed # 2 :

  • s : afirma para executar uma substituição
  • / : inicia o padrão
  • 2 : corresponde a um caractere 2
  • : : corresponde a um caractere :
  • [^ ]* : corresponde a qualquer número de caracteres que não seja
  • / : interrompe o padrão / inicia a sequência de substituição
  • 2:0 : adiciona uma 2:0 string
  • / : interrompe a sequência de substituição / inicia os sinalizadores de padrão
  • g : afirma para executar a substituição globalmente, ou seja, para substituir cada ocorrência do padrão na linha
por kos 13.05.2015 / 10:37
4

Este forro único usando sed

sed -i.bkp 's/2:\([0-9]*\)\|2:\(-\)\([0-9]*\)/2:0/g' input_file

na linha substituirá globalmente em input_file manterá um arquivo de backup chamado input_file.bkp no mesmo diretório.

Isso pode ser ainda mais curto usando regexes estendidas como sugerido por kos, como

sed -ri.bkp 's/2:\-?[0-9]*/2:0/g' input_file
    
por souravc 13.05.2015 / 10:45
2

Eu usaria um loop awk básico:

$ awk '{for (i=1; i<=NF; i++) $i~/^2:/ && $i="2:0"}1' file
1:20 2:0 3:0.432 2:0 10:12

Isso percorre todos os campos. Sempre que um deles começa com 2: , ele substitui tudo com 2:0 . Finalmente, o 1 significa True, para que toda a linha seja impressa.

    
por fedorqui 13.05.2015 / 11:27
1

Usando python :

#!/usr/bin/env python2
import re
with open('test_dir/unix_se.txt') as f:
    for line in f:
        print re.sub(r'(?:(?<=(?: 2:))|(?<=(?:^2:)))[^ ]*', '0', line).rstrip()

Aqui, usamos a função re.sub do módulo re .

  • re.sub() tem o padrão sub(pattern, repl, string, count=0, flags=0)

  • Como não usaremos mais os valores dentro do grupo, usamos a notação do grupo que não captura (?:)

  • (?:(?<=(?: 2:))|(?<=(?:^2:))) usa a largura zero positiva para trás para corresponder a 2: no início ou seguida por um espaço.

  • [^ ]* corresponderá a zero ou mais caracteres antes do espaço, após 2: e, em seguida, os substituirá por 0 .

Aqui está um exemplo:

Entrada:

2:456 1:20 2:25 3:0.432 2:-17 10:12
1:20 2:25 3:0.432 2:-17 10:12 2:543 2:-78

Saída:

2:0 1:20 2:0 3:0.432 2:0 10:12
1:20 2:0 3:0.432 2:0 10:12 2:0 2:0
    
por heemayl 13.05.2015 / 11:49
0

Thx @kos para a versão sed :

Algumas pequenas modificações para o perl way:

perl -pe 's/((^|\s)2:)[^\s]*/${1}0/g' testdata

Escreva de volta com:

perl -i -pe 's/((^|\s)2:)[^\s]*/${1}0/g' testdata

Explicação:

((^|\s)2:)[^\s]*

Demo do Debuggex

  • 1º grupo de captura ((^|\s)2:)

    • 2º grupo de captura (^|\s)
    • 1ª alternativa: ^

      ^ afirma a posição no início da string

    • 2ª alternativa: \s

      \s corresponde a qualquer caractere de espaço em branco [\r\n\t\f ]

    2: corresponde aos caracteres 2: literalmente

  • [^\s]* corresponde a um único caractere não presente na lista abaixo

    Quantificador: * Entre zero e ilimitado, tantas vezes quanto possível, devolvendo conforme necessário [ganancioso]

    \s corresponde a qualquer caractere de espaço em branco [\r\n\t\f ]

Ou com um Positive Look Behind , thx @steamdriver

perl -pe 's/(?<=2:)\S*/0/g' testdata

Explicação

(?<=2:)\S*

  • (?<=2:)Lookbehindpositivo-Afirmequeaexpressãoregularabaixopodesercorrespondida

    2:correspondeaoscaracteres2:literalmente

  • \S*correspondeaqualquercaracteredeespaçonãobranco[^\r\n\t\f]

    Quantificador:*Entrezeroeilimitado,tantasvezesquantopossível,devolvendoconformenecessário[ganancioso]

Demonstração do Debuggex

    
por A.B. 13.05.2015 / 12:12