Como extraio uma parte de uma instrução SQL para fins de pesquisa e substituição?

0

Estou usando o shell bash tentando fazer uma pesquisa e substituição. Eu tenho um arquivo de linhas parecidas com

...
INSERT INTO currency (name, code, symbol) VALUES ('Baht', 'THB', '฿');
...

e eu quero converter cada linha para ser

currency = Currency.find_by_iso('THB') || Currency.new(:code => 'THB')

Eu estou extraindo o segundo argumento do comando INSERT SQL como você pode ver. Eu pensei que poderia fazer isso

perl -w -pe "s/INSERT INTO currency (name, code, symbol) VALUES ('(.*?)', '(.*?)', '(.*?)');/currency = Currency.find_by_iso(\$&) || Currency.new(:code => '\$&')/" currencies.rb

mas nada está acontecendo - isto é, a saída da substituição está deixando as linhas inalteradas. Como capturar o segundo valor da minha instrução SQL e criar uma nova linha a partir dele?

    
por Dave 29.08.2017 / 23:24

1 resposta

1

the output of the replacement is leaving the lines unchanged

Isso indica que sua regex não está combinando com a entrada, então vamos dar um passo para trás e ver se conseguimos uma regex mínima que funcione:

perl -w -pe "s/INSERT INTO currency (name, code, symbol) VALUES ('(.*?)', '(.*?)', '(.*?)');//" currencies.rb
> INSERT INTO currency (name, code, symbol) VALUES ('Baht', 'THB', '?');

Simplesmente removeu a substituição e, sem surpresa, não há diferença para o que você conseguiu, não está combinando com a entrada.

Agora, a última parte do seu regex ('(.*?)', '(.*?)', '(.*?)') contém um conjunto de caracteres que têm um significado especial no regex, portanto, vamos removê-los e ver se isso funciona:

perl -w -pe "s/INSERT INTO currency (name, code, symbol) VALUES .*;//" currencies.rb
> INSERT INTO currency (name, code, symbol) VALUES ('Baht', 'THB', '?');

Ainda não corresponde, agora os únicos caracteres especiais são o () , que provavelmente deve ser ignorado:

perl -w -pe "s/INSERT INTO currency \(name, code, symbol\) VALUES .*;//" currencies.rb
> 

Sim que corresponde - nossa entrada foi correspondida e excluída, então vamos adicionar o bit final novamente, desta vez também escapando dos outros () s:

perl -w -pe "s/INSERT INTO currency \(name, code, symbol\) VALUES \('(.*?)', '(.*?)', '(.*?)'\);//" currencies.rb
> 

Ainda corresponde, então vamos adicionar a substituição novamente:

perl -w -pe "s/INSERT INTO currency \(name, code, symbol\) VALUES \('(.*?)', '(.*?)', '(.*?)'\);/currency = Currency.find_by_iso(\$&) || Currency.new(:code => '\$&')/" currencies.rb
> currency = Currency.find_by_iso(INSERT INTO currency (name, code, symbol) VALUES ('Baht', 'THB', '?');) || Currency.new(:code => 'INSERT INTO currency (name, code, symbol) VALUES ('Baht', 'THB', '?');')

Hmm, parece coincidir com a parte errada. Isso ocorre porque & é substituído pela expressão combinada inteira em vez de um único subgrupo, em vez disso, você deseja $1 , $2 etc:

perl -w -pe "s/INSERT INTO currency \(name, code, symbol\) VALUES \('(.*?)', '(.*?)', '(.*?)'\);/currency = Currency.find_by_iso(\) || Currency.new(:code => '\')/" currencies.rb
> currency = Currency.find_by_iso(THB) || Currency.new(:code => 'THB')

Quase lá, perdendo algumas aspas - nós também não precisamos das outras duas correspondências de subgrupos, então vamos removê-las:

perl -w -pe "s/INSERT INTO currency \(name, code, symbol\) VALUES \('.*?', '(.*?)', '.*?'\);/currency = Currency.find_by_iso('\') || Currency.new(:code => '\')/" currencies.rb 
> currency = Currency.find_by_iso('THB') || Currency.new(:code => 'THB')

Lá vamos nós, exatamente o que queríamos.

Quando se depara com um regex complexo que parece não funcionar, normalmente é um problema com alguns dos caracteres especiais, varia de idiomas para idiomas e de ferramenta para ferramenta - às vezes, as coisas precisam ser escapadas, às vezes, não. É sempre útil começar tirando esses caracteres com alternativas mais simples até obter um regex que corresponda a parte de sua entrada, mesmo que não seja exatamente a parte que você deseja - e então expanda-a de lá, pouco a pouco, até que ela quebre ou Você consegue o que quer. Se você achar que o ponto está quebrado, leia a documentação do idioma / ferramenta que está usando para descobrir a sintaxe que está procurando.

    
por 30.08.2017 / 02:13