Escapar do blackslash em sed

4

Estou tentando gravar um comando sed para substituir uma linha em um arquivo. A substituição de sed exigia o diretório de trabalho atual, que começa a tornar o comando um pouco confuso por causa dos caracteres que precisam ser escapados.

Aqui está o que eu tenho até agora:

sed -i "s/^log.*$/log 'echo pwd | sed 's/\//\\//g''\/redis\/redis.log\/" ./conf/redis.conf

No entanto, isso me dá um erro com sed.

Eu tentei dividi-lo em comandos mais fáceis:

user@ubuntu:~/project$pwd | sed 's/\//\\//g'
\/home\/user\/project

Isso retorna o que eu quero, mas quando tento adicionar na substituição de comando, ele falha:

user@ubuntu:~/project$ echo 'pwd | sed 's/\//\\//g''
sed: -e expression #1, char 9: unknown option to 's'

Qualquer ajuda seria apreciada

    
por Franz Payer 16.01.2014 / 19:37

2 respostas

7

Se eu estou lendo isso corretamente, você está tentando substituir barras ( / ) por uma barra invertida ( \/ )? Isto recebe um lote mais fácil de manusear se você não usa / como seu delimitador em sed :

~ $ pwd | sed 's_/_\/_g''
\/home\/username
~ $ echo "$( pwd | sed 's_/_\/_g' )"
\/home\/username
    
por 16.01.2014 / 19:50
2

Você está se preparando para alguma complicação aqui, já que barras invertidas são interpretadas

  1. pelo shell dentro da substituição do comando,
  2. pelo shell fora da substituição do comando,
  3. por sed.
Primeiro, não use a forma backtick de substituição de comando: suas regras para citações internas são intrincadas. Use parênteses em dólar, que tem regras intuitivas - o que está dentro é analisado normalmente, com o parêntese próximo correspondente marcando o fim da subcamada.

Então você está usando aspas duplas para um comando sed. Evite isso: seu comando sed não pode ser escrito literalmente, você precisa proteger \ e $ para o shell e para o sed. Use aspas simples em vez disso.

Além disso, você tem barras no texto de substituição. Sed não pode saber que essas barras não fazem parte de sua sintaxe, mas texto literal que você deseja incluir. Você pode usar um caractere diferente de / para delimitar um comando s , g ou m . Use um personagem que nunca aparece no seu texto substituto (felizmente, aqui, é fácil porque você conhece o texto de substituição).

Presumo que echo pwd deve ser realmente pwd (ou echo "$PWD" ). Sem a necessidade de proteger as barras, você não precisa da chamada sed aninhada. Se você precisou transformar pwd , considere usar $PWD e os recursos de manipulação de string do shelll.

sed -i 's~^log.*$!log '"$PWD"'/redis/redis.log!' ./conf/redis.conf

Se você tiver dificuldades com as citações, não hesite em usar uma ferramenta mais fácil, como o Perl. O Perl combina os recursos do sed e do shell, para que você não encontre problemas entre os dois.

perl -MCwd -i -pe 'BEGIN {$PWD = cwd} s[^log.*][log $PWD/redis/redis.log]' conf/redis.conf

ou

perl -MCwd -i -pe '$_ = cwd."/redis/redis.log" if /^log' conf/redis.conf
    
por 17.01.2014 / 01:26