Pergunta sobre sed – sed: substituir parte de uma linha

34

Como se pode substituir uma parte de uma linha por sed?

A linha

DBSERVERNAME     xxx

deve ser substituído por:

DBSERVERNAME     yyy

O valor xxx pode variar e há duas guias entre dbservername e o valor. Esse par de nome e valor é um dos muitos de um arquivo de configuração.

Eu tentei com a seguinte referência anterior:

echo "DBSERVERNAME    xxx" | sed -rne 's/\(dbservername\)[[:blank:]]+\([[:alpha:]]+\)/\1 yyy/gip'

e isso resultou em um erro: referência inválida \ 1 no comando `s` do comando RHS.

O que há de errado com a expressão? Usando o GNU sed.

Sua resposta

7   a resposta
42

Isso funciona:

sed -rne 's/(dbservername)\s+\w+/\1 yyy/gip'

(Quando você usa a opção -r, você não precisa escapar dos parênteses.)

Pouco de explicação:

-r é expressões regulares estendidas - faz diferença em como o regex é escrito.-n não imprime a menos que especificado -sed imprime por padrão, caso contrário,-e significa o que segue é uma expressão. Vamos quebrar a expressão:s/// é o comando para search-replace, e o que está entre o primeiro par é o regex para combinar, e o segundo par é o substituto,gip, que segue o comando search replace;g significa global, isto é, todos os jogos, em vez de apenas o primeiro, serão substituídos por uma linha;i é insensibilidade a casos;p significa imprimir quando terminar (lembre-se-n bandeira de mais cedo!),Os colchetes representam uma parte da correspondência, que surgirá mais tarde. assimdbservername é a primeira parte do jogo\s é espaço em branco,+ significa um ou mais*, zero ou mais) ocorrências,\w é uma palavra, que é qualquer letra, dígito ou sublinhado,\1 é uma expressão especial para o GNUsed que imprime a primeira correspondência entre colchetes na pesquisa que a acompanha.
Eu sei que vocês têm muita experiência em comandos de shell ... mas por favor, se preocupem com os aspirantes a noobs de linux sempre que possível .... tudo dentro'' precisa ser explicado ... ou eu tenho que passar pelo tododoc Mahesha999
1

Isso pode funcionar para você:

echo "DBSERVERNAME     xxx" | sed 's/\S*$/yyy/'
DBSERVERNAME     yyy
1

Você não deveria estar fugindo de seus parênteses. Experimentar:

echo "DBSERVERNAME    xxx" | sed -rne 's/(dbservername)[[:blank:]]+([[:alpha:]]+)/\1 yyy/gip'
2

Você está escapando do seu (e). Tenho certeza que você não precisa fazer isso. Experimentar:

sed -rne 's/(dbservername)[[:blank:]]+\([[:alpha:]]+\)/\1 yyy/gip'
1

Você não deve estar fugindo quando usa aspas simples. ie.

echo "DBSERVERNAME    xxx" | sed -rne 's/(dbservername[[:blank:]]+)([[:alpha:]]+)/\1 yyy/gip'
8

Outros já mencionaram o escape de parênteses, mas por que você precisa de uma referência de volta, se a primeira parte da linha é constante?

Você poderia simplesmente fazer

sed -e 's/dbservername.*$/dbservername yyy/g'
Isso obtém meu voto porque é a solução mais simples para um problema simples. Usar uma referência anterior evita que você digitue erroneamente as duas cópiasdbservername. É óbvio aqui, mas quando eu modifico postgresql.conf em sed acho difícil ver de relance se eu digiteilisten_address oulisten_addresses (postgresql.conf). Ambos parecem plausíveis, mas apenas um está correto. Iain Samuel McLean Elder
Bom ponto! Eu tinha acabado de aprender sobre o uso de regexps + sed e a mente apenas decidiu 'regexp' ao ver esta tarefa em particular, então como 'jwz' disse 'Eu tive dois problemas' (embora não diretamente devido aos regexps) :) calvinkrishy
0

Tente isso

sed -re 's/DBSERVERNAME[ \t]*([^\S]+)/\yyy/ig' temp.txt

ou isto

awk '{if($1=="DBSERVERNAME") $2 ="YYY"} {print $0;}' temp.txt

Perguntas relacionadas