Usando sed para substituir uma string por caracteres especiais com outra string com caracteres especiais

1

Estou tentando automatizar a troca de um prompt bash por outro em .bashrc

Original String:

PS1='${debian_chroot:+($debian_chroot)}\[3[01;31m\]\u@\h\[3[00m\]:\[3[01;34m\]\w\[3[00m\]\$ '

Strings de substituição:

IPeth0=$(Adr=$(ifconfig eth0 |grep inet); echo $Adr | awk '{print $2}' | cut -c 6- )
PS1='\d \t \[\e[0;31m\]\u@$IPeth0\[\e[0;32m\]:\[\e[0;36m\]\w# \[\e[m\] '

Uma das muitas tentativas ruins de escrever bash para fazer isso:

#!/bin/bash
original="PS1='${debian_chroot:+($debian_chroot)}\[3[01;31m\]\u@\h\[3[00m\]:\[3[01;34m\]\w\[3[00m\]\$ '"
replacement="PS1='\d \t \[\e[0;31m\]\u@$IPeth0\[\e[0;32m\]:\[\e[0;36m\]\w# \[\e[m\] '" 
ipvar="IPeth0=$(Adr=$(ifconfig eth0 |grep inet); echo $Adr | awk '{print \}' | cut -c 6- )"

cp ~/.bashrc ~/.bashrc.bak
sed -e 's/$original/$replacement/g' ~/.bashrc

Eu tentei escapar em dobro de todos os caracteres porque sei que o sed precisa de '\', '/' e '&' escapou. Eu simplesmente não consigo envolver minha cabeça em torno desta.

Eu nem me incomodei em tentar obter a linha IP imediatamente porque não pude substituir a primeira linha.

Se houver algum método melhor para este tipo de automação, por favor me avise, estou aberto a qualquer coisa.

    
por daedalus 09.05.2015 / 02:12

1 resposta

1

Aqui estão algumas abordagens (bem, 2½):

  • Se você tem interesse em poder para modificar incrementalmente as configurações de PS1 que seguem um modelo geral,

    • Crie um arquivo que contenha apenas a linha PS1=… .
    • Escreva os comandos sed para editá-lo, peça por peça; por exemplo.,
      • sed -e 's/${debian_chroot:+($debian_chroot)}/\d \t /'
      • sed -e 's/\033/\e/g'
      • etc.
    • Você pode achar mais fácil depurar esses comandos menores e mais simples. Quando você tiver todos eles trabalhando, deve ser fácil costurá-los juntos.
    • Você observou o valor de $original ? Por exemplo, você já fez printf "%s\n" "$original"
      ? Lembre-se, quando você diz algo como

      "The quick brown fox 'jumps over' the lazy dog."
      

      A string inteira está em duplo citações. Então quando você diz

      "Humpty '$var' Dumpty"
      

      O $var é expandido porque está entre aspas duplas.

      Agora olhe para sua string original :

      original="PS1='${debian_chroot:+($debian_chroot)}\[3[01;31m\]\u@\h\[3[00m\]:…"
      

      O ${debian_chroot:+($debian_chroot)} é expandido quando você faz essa tarefa. Então isso é um problema.

  • Se você quiser apenas alterar PS1 para seu novo valor, independentemente do que já está lá, não tente esculpir a estátua da raposa e então adicione argila na esperança de criar uma estátua de um cachorro; basta apagar a atribuição existente e substituí-la, usando o comando sed c ( c hange), que substitui um grupo de uma ou mais linhas com outro grupo de uma ou mais linhas:

    sed -e $'/^PS1=/c\
    IPeth0=$(Adr=$(ifconfig eth0 |grep inet); echo $Adr | awk \'{print $2}\' | cut -c 6- )\
    PS1=\'\d \t \[\e[0;31m\]\u@$IPeth0\[\e[0;32m\]:\[\e[0;36m\]\w# \[\e[m\] \''
    

    Eu coloquei toda a string de comando sed em $'…' então eu poderia usar \' para obter caracteres ' não processados na string. Se preferir, você pode usar o provado e verdadeiro

    '$not_a_variable …'"… please don't try to expand those …"'… $not_a_variable'
    
    técnica de

    (alternância de cotações).

  • Uma variante acima é

    sed -e $'/^PS1=/{s/^/# /; a\
    IPeth0=$(Adr=$(ifconfig eth0 |grep inet); echo $Adr | awk \'{print $2}\' | cut -c 6- )\
    PS1=\'\d \t \[\e[0;31m\]\u@$IPeth0\[\e[0;32m\]:\[\e[0;36m\]\w# \[\e[m\] \'
    }'
    

    que comenta a definição existente ( s/^/# / ) e a pende as novas linhas com o comando a .

por 09.05.2015 / 03:40