Como você obtém o SED para substituir apenas o primeiro conjunto de caracteres em uma expressão de pesquisa?

1

Basicamente, acho que essa questão é mais de regex do que de SED diretamente, mas é o SED que estou usando, então é de onde estou começando.

Eu tenho um arquivo de configuração web.config para um site do ASP.NET 2.0 para o qual estou automatizando o processo de criação. Estou usando o UNIXUtils para me dar um pouco mais de poder sobre o que é fornecido pelo Windows. Usando o SED, alguém pode me esclarecer sobre como eu realizaria o seguinte:

Alterar

Data Source=RANDOM-SERVER;Initial Catalog=SomeDatabase;Persist Security Info=True;User ID=MyUser;Password=*************;

Para

Data Source=PRODUCTION-SERVER;Initial Catalog=SomeDatabase;Persist Security Info=True;User ID=MyUser;Password=*************;

Eu tentei o seguinte

sed s"|Data Source=.*;|Data Source=PRODUCTION-SERVER;|g"

mas o que recebo é

Data Source=PRODUCTION-SERVER;

i.e. sed está sendo extremamente ganancioso e comendo todos os personagens até o último ponto e vírgula, pelo menos é o que parece estar fazendo.

BTW: Sim, eu gostaria de manter o operador guloso no final para garantir que a alteração seja aplicada a todas as ocorrências no arquivo original, embora, em teoria, não devesse existir.

Se alguém puder me mostrar como fazer isso, ficarei muito grato, embora suspeite que não haja uma maneira fácil de fazer isso, já que não consegui encontrar nada na rede que atenda aos meus requisitos. Irritantemente todo mundo está focado em caminhos de uma forma ou de outra.

Se não puder ser feito no SED, mas pode ser feito usando outra coisa na suíte UNIXUtils padrão, então essa é uma resposta aceitável, estou aberto a sugestões.

    
por Greg 22.08.2013 / 11:37

2 respostas

2

Use um grupo de caracteres não correspondente ( [^;] ) em vez de ponto ( . ), por exemplo:

sed s"|Data Source=[^;]*|Data Source=PRODUCTION-SERVER|"

Observe que o sinalizador global ( g ) no final significa "substitua todas as ocorrências na linha atual" e não é voraz.

    
por 22.08.2013 / 11:42
1

Até onde eu sei, sed não tem como fazer correspondência não-gananciosa, seus regexes são sempre gananciosos (e como já apontado a g flag significa coincidir com todas as ocorrências na linha atual, ele irá procurar o arquivo inteiro por padrão).

Eu faria isso usando um grupo de caracteres como sugerido por @Thor ou usando uma ferramenta que suporte não partidas gananciosas como Perl:

perl -pne 's/Data Source=.+?;/Data Source=PRODUCTION-SERVER;/' file 

Em regex Perl, a construção +? significa encontrar pelo menos um ( + ) mas o mínimo possível ( ? ) caracteres correspondentes. O -p significa imprimir cada linha e o -n significa ler o arquivo de entrada linha por linha e aplicar o script fornecido como um argumento para -e . Por fim, você também pode editar o arquivo com a opção i :

perl -i -pne 's/Data Source=.+?;/Data Source=PRODUCTION-SERVER;/' file 
    
por 22.08.2013 / 14:48

Tags