Editando uma declaração sed

2

Estou escrevendo um script para alterar rapidamente a home page do firefox por meio de uma variável de texto:

sed -i 's|\("browser.startup.homepage",\) "\(.*\)"| "$ddrs"|' /home/max/.mozilla/firefox/*.default/prefs.js

Eu preciso ignorar o problema de expandir a variável $ddrs dentro da instrução de cotação única sed .

    
por Symb932 17.12.2015 / 03:35

5 respostas

0

ENCONTROU UMA SOLUÇÃO POR MIM MESMO
Em vez de insistir em algo legal como substituir uma sequência de segmentação dentro de uma linha, optei por substituir toda a linha, por isso:

  1. Primeiro, coloquei o arquivo urls.txt no diretório ~/.mozilla/firefox/*.default/ .
  2. Em seguida, escrevi o código a seguir no início do arquivo /usr/lib/firefox/firefox.sh :
ddrs=$(shuf -n1 ~/.mozilla/firefox/*.default/urls.txt)
nwli="user_pref(\"browser.startup.homepage\", "$ddrs");"
sed -i "/browser.startup.homepage/c\$nwli" ~/.mozilla/firefox/*.default/prefs.js
    
por 21.12.2015 / 07:58
3

Para menos informações sobre caracteres especiais, como aspas duplas ( e $ , se você usá-lo ), basta colocar a variável entre aspas duplas e o resto entre aspas simples. Não há espaços entre.

's|\("browser.startup.homepage",\) "\(.*\)"| '"$ddrs"' |'

Em uma nota separada, como você não se refere ao segundo valor, não há motivo para usar parênteses:

's|\("browser.startup.homepage",\) ".*"| '"$ddrs"' |'

Da mesma forma, se você quiser que o valor da variável $ddrs apareça entre aspas duplas no arquivo que você está editando, será necessário incluir essas aspas duplas:

's|\("browser.startup.homepage",\) ".*"| "'"$ddrs"'" |'

Mas, me ocorre que você provavelmente tem mais de um valor em uma única linha (ou você poderia ter.) Como os regexes sed são gananciosos, seu .* corresponderá ao restante da linha até a última citação last . Para torná-lo não-ganancioso (para este caso de uso específico), use uma classe de caractere que corresponda a qualquer coisa, exceto às aspas duplas:

's|\("browser.startup.homepage",\) "[^"]*"| "'"$ddrs"'" |'

E, embora uma coincidência acidental seja improvável, os pontos ( . ) na primeira seqüência não são pontos correspondentes, eles estão combinando a classe de caractere "qualquer caractere único". Para evitar que você escape deles:

's|\("browser\.startup\.homepage",\) "[^"]*"| "'"$ddrs"'" |'

Parece que você está usando um delimitador de vírgula, mas corresponde a um espaço APENAS após a vírgula - não dois espaços ou zero. Eu suspeito que qualquer número de espaços seja possível , então, para robustez, permita espaços arbitrários entre a vírgula e as aspas duplas:

's|\("browser\.startup\.homepage",\) *"[^"]*"| "'"$ddrs"'" |'

Não há outras questões óbvias aqui. (1) O espaço à esquerda que assumirei é deliberado; (2) Suponho que | é um caractere bastante seguro para assumir que não estará na URL (o conteúdo de $ddrs ). O escape aqui é um pesadelo para ler, mas para este uso específico especificamente em sed eu acho que é inevitável.

A robustez é mais importante do que a legibilidade, embora seja boa a legibilidade para se esforçar para não sacrificar a robustez.

    
por 17.12.2015 / 04:24
2

Não seria mais simples configurar sua página inicial para um único URL que retornasse um redirecionamento para uma página aleatória do banco de dados de URLs da sua página inicial?

Dessa forma, a randomização da página inicial ocorreria toda vez que você clicasse em Página inicial (ou abrisse uma nova guia / página que fosse para Página inicial) em vez de apenas todas as vezes que você reiniciasse o navegador. Também evitaria ter que mexer com sua configuração do firefox o tempo todo.

Para fazer isso, a maneira mais simples seria instalar um servidor web minimalista em algum lugar que suportasse scripts CGI e escrever um CGI simples que emitisse um redirecionamento de URL em cada solicitação, com as URLs provenientes de um banco de dados simples (até mesmo um texto). arquivo faria).

    
por 17.12.2015 / 05:56
0

Tente usar aspas " para incluir todo o argumento sed e excluir as citações existentes, como esta:

sed -i "s|\(\"browser.startup.homepage\",\) \"\(.*\)\"| \"$ddrs\" |" /home/max/.mozilla/firefox/*.default/prefs.js

Explicação

O argumento original que você está passando para o sed parece assim:

's|\("browser.startup.homepage",\) "\(.*\)"| "$ddrs" |'
  • usa a sintaxe s|search|replace| ,
  • , mas incluído com as aspas literais ' , que bloqueia a expansão do bash de $ddrs , é por isso que $ddrs não foi expandido por Bash

Nós simplesmente modificamos esse argumento para:

"s|\(\"browser.startup.homepage\",\) \"\(.*\)\"| \"$ddrs\" |"
  • no entanto, como estamos usando " quotes, precisamos escapar do original " substituindo-os por \"
  • uma vez que agora é incluído apenas em " quote, o Bash expandirá com sucesso $ddrs
por 17.12.2015 / 04:05
0

Você realmente deve escapar completamente de qualquer dado variável que você queira usar em um regexp. Por exemplo:

printf %s\n "$ddrs" |
sed  -e'# the RHS field needs backslashes'  \
     -e'# delimiter, and newlines escaped.' \
     -e'H;1h;$!d;g;s|[\/]|\&|g;s|\n|\&|g' \
     -e'# now the string is s/// safe, so ' \ 
     -e's|.*|s/\("browser\.startup\.homepage",\) ".*"/\1 "&"/|' |
sed -i "" -f- ./path/to/your/edit/file
    
por 17.12.2015 / 04:46