precisa substituir o conteúdo de um arquivo

3

Estou preso em uma situação. Eu tenho um arquivo script.txt com conteúdo

$cat script.txt

SET TABLESPACE CONTAINERS FOR 3
-- IGNORE ROLLFORWARD CONTAINER OPERATIONS
USING (
FILE '/db2data2/dbs/rahtest/rahtest1.lrg'  5120
);


SET TABLESPACE CONTAINERS FOR 4
-- IGNORE ROLLFORWARD CONTAINER OPERATIONS
USING (
  FILE   '/db2data2/dbs/rahtest/rahtest2.lrg'  5120
);

Meu requisito é o sistema de arquivos nas linhas

FILE '/db2data2/dbs/rahtest/rahtest1.lrg' 5120
FILE   '/db2data1/dbs/rahtest/rahtest2.lrg'  5120

Eu preciso substituir

/db2data2/dbs/rahtest/rahtest1.lrg

e

/db2data2/dbs/rahtest/rahtest2.lrg

com outros sistemas de arquivos; diga

/db2data3/dbs/rahtest/rahtest1.lrg

e

/db2data3/dbs/rahtest/rahtest2.lrg

respectivamente.

Outras partes devem ser as mesmas. Minha saída é tal que as linhas sejam agora -

FILE '/db2data3/dbs/rahtest/rahtest1.lrg'  5120
FILE '/db2data3/dbs/rahtest/rahtest2.lrg'  5120

Ele deve refletir no meu arquivo. Eu não sei a posição das linhas na linha. Eu tentei com sed. Eu tentei colocar as linhas em variáveis, digamos var1 e var2

var1='echo /db2data2/dbs/rahtest/rahtest1.lrg'
var2='echo /db2data2/dbs/rahtest/rahtest2.lrg'
var3='echo /db2data3/dbs/rahtest/rahtest1.lrg'
var4='echo /db2data3/dbs/rahtest/rahtest2.lrg'

quando tentei fazer

sed 's/$var/$var3' script.txt

falha como / está lá. Eu estou usando o AIX. Meus arquivos finais devem ser assim -

SET TABLESPACE CONTAINERS FOR 3
-- IGNORE ROLLFORWARD CONTAINER OPERATIONS
USING (
FILE '/db2data3/dbs/rahtest/rahtest1.lrg'  5120
);


SET TABLESPACE CONTAINERS FOR 4
-- IGNORE ROLLFORWARD CONTAINER OPERATIONS
USING (
  FILE   '/db2data3/dbs/rahtest/rahtest2.lrg'  5120
);
    
por Rahul Mukerjee 25.12.2015 / 12:50

2 respostas

7

Quando houver um / no texto, você poderá usar um caractere diferente, por exemplo, um | como o separador para os argumentos do sed. Além disso, ao usar variáveis, você precisa usar aspas duplas ( "" ) para o comando sed , porque as variáveis não são expandidas entre aspas simples. Tente isto:

var1='/db2data2/dbs/rahtest/rahtest1.lrg'
var2='/db2data2/dbs/rahtest/rahtest2.lrg'
var3='/db2data3/dbs/rahtest/rahtest1.lrg'
var4='/db2data3/dbs/rahtest/rahtest2.lrg'

sed -e "s|$var1|$var3|g" -e "s|$var2|$var4|" script.txt
    
por 25.12.2015 / 13:13
0

Para lidar de forma robusta com informações variáveis em expressões regulares, você precisa escapar dos metacaracteres da expressão regular. Esta pergunta foi respondida muitas vezes - eu fiz pessoalmente muitas vezes - mas aqui está o básico:

^$*[]\.

^ Esses são metacaracteres de expressão regular básica. Cada um deles tem um significado especial em uma expressão regular como sintaxe e não são interpretados literalmente. O significado de vários deles é, na verdade, dependente da posição e, por isso, às vezes may consegue incluí-los em uma expressão regular sem o escape adequado, mas isso não significa que você deveria - especialmente quando a expressão regular é construída de entrada não validada.

Mas tem mais:

delimiter newline &

^ Esses são caracteres de sintaxe de substituição sed s/// ubstitution. O delimitador - que é tradicionalmente / - é variável e sed interpretará automaticamente como o primeiro caractere após um s para um novo comando.

A nova linha - no lado esquerdo da expressão regular da declaração - é positivamente inescapável. É inválido lá. A única maneira de substituir uma nova linha é usar o \n escape - mas a única maneira de obter uma nova linha no espaço padrão que pode ser encontrada em uma expressão regular é colocar uma lá você mesmo - e então isso geralmente não é um problema. No lado direito da s/// ubstitution - o lado replace - a nova linha é passível de escape - como todo o resto - com \ , que é o metacaractere de escape. O mesmo é verdade para & .

E para criar um script robusto de sed de variáveis, você precisa escapar dele. Esse é o único caminho. Alterar o delimitador porque você espera que haja um em sua instrução não é um método robusto. Você valida entrada e descarta qualquer chance de erros de sintaxe, ou você evita caracteres de sintaxe para indicar o que pretende. Essas são as duas maneiras de escrever programas robustos - não há outros.

Felizmente, sed torna isso muito fácil. Como mencionado - a barra invertida \ é o metacaractere de escape e até escapará quando for duplicada. E assim podemos usar sed para escapar de sed .

printf %s\n "$regex_field" "$replace_field" |
sed -ne'h;n' -e's|[\&/]|\&|g'               \
    -ex      -e's|[]/\.$^*[]|\&|g'          \
    -eG      -e's|\(.*\)\n\(.*\)|s///|p' |
sed -f-      edit_file

Veja? A entrada é separada em novas linhas e, portanto, conforme escrita, não é permitida uma nova linha em $regex_field ou $replace_field . Você poderia lidar com isso também, mas isso não acontece e a expectativa é que a entrada seja validada para descartá-la.

Em qualquer caso, as linhas de entrada são alimentadas com o primeiro sed em pares e h olds uma cópia da primeira metade de cada par de linhas e pula n ext para o segundo, quando ele escapa os caracteres relevantes para o lado direito de uma declaração sed s/// ubstitution. Em seguida, e x altera seus espaços de retenção e padrão e escapa para o lado esquerdo, antes de G etting o RHS anexado ao LHS como separado por um delimitador \n ewline. A última coisa que tem que fazer é adicionar os s/// bits antes de p rinting o comando escapado para o padrão.

O segundo sed lê seu arquivo de script em - (que geralmente é interpretado como padrão, mas você pode querer tentar /dev/fd/0 se não) e então aplica isso script para o seu nome edit_file .

    
por 25.12.2015 / 18:11

Tags