Eu tenho um arquivo que tem um monte de nomes de host correlacionados com IPs que se parece com isso:
x-cluster-front-1 192.168.1.2
x-cluster-front-2 192.158.1.10
y-cluster-back-1 10.1.11.99
y-cluster-back-2 10.1.157.38
int.test.example.com 59.2.86.3
super.awesome.machine 123.234.15.6
Eu quero que fique assim:
x-cluster-front-1 192.168.1.2
x-cluster-front-2 192.158.1.10
y-cluster-back-1 10.1.11.99
y-cluster-back-2 10.1.157.38
int-test-example-com 59.2.86.3
super-awesome-machine 123.234.15.6
Como posso substituir o. (pontos) da primeira coluna com - (hífen) para facilitar a classificação pela segunda coluna? Eu estava pensando em usar o sed para substituir pontos até o primeiro espaço ou substituir todos os pontos, exceto os três últimos, mas estou tendo problemas para entender regex e sed. Eu posso executar substituições simples, mas isso está passando da minha cabeça!
Isso faz parte de um script maior que eu tenho escrito no bash. Estou preso nessa parte.
awk
é baseada emnawk
, portanto, todas asawk
implementações modernas devem tergsub
. No Solaris, você pode precisar/usr/xpg4/bin/awk
ounawk
.Se você precisar fazer as substituições no primeiro campo, o melhor é usar a solução awk de Rahul, mas cuidado, isso pode afetar o espaçamento (os campos são reescritos com um único espaço entre eles).
Você pode evitá-lo escrevendo-o:
O
-p
sinalizador significa "leia o arquivo de entrada linha por linha e imprima cada linha após aplicar o script fornecido por-e
". Em seguida, substitua (s|pattern|replacement|
) a primeira sequência de caracteres não espaciais (\S+
) pelo padrão correspondente ($&
) depois de substituir todos.
por-
. O truque é usars|||e
onde oe
operador avaliará uma expressão como uma substituição. Portanto, você pode ter uma substituição (tr/./-/
) aplicada à partida ($&
) da anterior (s|||e
).Se você precisar substituir todos
.
por um,-
exceto os três últimos, pelo GNUsed
e supondo que você tenha umrev
comando:fonte
/r
que funcione).O Sed não é a ferramenta mais fácil para o trabalho - veja outras respostas para obter melhores ferramentas - mas pode ser feito.
Para substituir
.
por-
apenas até o primeiro espaço, o usos
em um loop.(Observe que algumas implementações sed não suportam comentários na mesma linha. GNU sed sim.)
Para executar a substituição até o último espaço:
Outra técnica utiliza o espaço de espera do sed. Salve o bit que não deseja modificar no espaço de espera, faça seu trabalho e depois recupere o espaço de espera. Aqui, divido a linha no último espaço e substituo pontos por traços na primeira parte.
fonte
Como Rahul deu a resposta canônica para seu caso de uso, pensei em responder ao problema titular: substituindo todas, exceto as últimas x ocorrências de uma regex:
O código acima (testado) não pressupõe que você tenha campos separados por espaço. Ele substituirá todos os pontos em uma linha por traços, exceto os últimos 3 pontos. Substitua o
3
código ao seu gosto.fonte
Você pode usar muitas ferramentas diferentes para isso. Rahul Patil já deu uma,
gawk
então aqui estão algumas outras:perl
A
-a
opção faz com que o perl divida automaticamente as linhas de entrada no espaço em branco e salve os campos resultantes na matriz@F
. O primeiro campo, portanto, será, portanto,$F[0]
substituiremos (s///
) todas as ocorrências de.
por-
no primeiro campo e, em seguida, imprimiremos toda a matriz.Concha
Aqui, o loop while lê o arquivo e divide automaticamente em espaço em branco. Isso cria dois campos
$first
e$rest
. A construção${first//pattern/replacement}
substitui todas as ocorrências depattern
comreplacement
.fonte
perlrun(1)
lhe dirá que-a
é "modo autosplit", prefiro pensar nisso como "awk
modo": DEu acredito que isso é um pouco mais fácil de ler do que um grande regex desagradável. Basicamente, eu apenas divido a linha em dois campos no espaço em branco e usei sed na primeira parte.
Dependendo do seu shell, você também pode usar $ {host //./-} em vez do comando sed.
fonte
Sem usar
g
no final do comando, você pode fazer isso ... Isso substituirá simplesmente a 1ª ocorrência do padrãofonte