Comando complexo sed com AND / OR / NOT

1

Eu tenho um monte de arquivos php que tem muitos comandos select .

Em cada consulta eu quero inserir uma variável coloumn admin_id = '$admin_id' ou seja, se a consulta for select * from users where abc='xyz' and qwe='fgh' , a consulta deverá ser convertida em select * from users where admin_id = '$admin_id' and abc='xyz' and qwe='fgh' .

Para fazer isso eu executei o seguinte comando sed -i "s/\(\"select.*\)where / where admin_id = '\$admin_id' and /" *.php .

Os itens acima funcionaram com sucesso, mas ainda estão enfrentando problemas com consultas SQL em que não há where na consulta, ou seja, select * from users . Como posso inserir admin_id = '$admin_id' nessas consultas também?

The queries in php files are executed by passing the query to the function in following way : execute_query("select * from $table order by username");

Grep

I can find the queries still which are left to be modified by executing : grep 'execute_query' *| grep select| grep -v admin_id > stillleft.txt

    
por Shahrukh Khan 06.01.2016 / 18:16

2 respostas

0

Se você insistir em usar sed, você pode usar dois comandos s sucessivos. Para evitar que o segundo seja executado após o primeiro na mesma linha, adicione um comando t entre; isso pula todos os comandos restantes se o comando anterior s fez uma substituição.

sed -e "s/\"select[^\";]* where /&admin_id = '\$admin_id' and /" -e t \
    -e "s/\"select[^\"]*/& where admin_id = '\$admin_id' /" \
    -i  *.php

Tenha em atenção que isto não é robusto: não irá lidar com cláusulas select em que a seleção de campo é dividida em várias linhas; não irá lidar com consultas que não tenham where mas, por ex. um group by na mesma linha, ele será danificado se uma consulta contiver where como substring, etc. Revise as entradas e saídas para certificar-se de não atingir nenhum dos casos problemáticos.

Com o perl, você pode usar um operador de repetição não ganancioso para interromper a correspondência na primeira palavra reservada ou fim da consulta. Isso ainda é aproximado, mas um pouco mais robusto. O Perl também permite que a substituição seja uma expressão arbitrária que construa a string de substituição (com o sufixo e após a substituição), para que possamos colocar uma condição lá.

perl -i -p -e '
    s[("select.*?)(\b(?:where|group|having|order|limit|procedure|into|for|lock)\b|[;"]|$)]
     [$1 . " where admin_id = '\$admin_id' " . ($2 eq "where" ? "and" : $2)]e
' *.php

P.S. que "…'$admin_id'…" parece uma injeção SQL esperando para acontecer, a menos que $admin_id não possa conter ' (e eu acho que o UTF-8 mal formado também pode ser problemático).

    
por 07.01.2016 / 01:30
-1

Se tudo o que você deseja é adicionar admin_id = '$admin_id' and após users e, após where quando estiver presente, você pode fazer o seguinte:

sed "s/\(select.*\)users[ ]*\(where\)\{0,1\}/ users where admin_id = '\$admin_id' and /" *.php

Coloque o sinalizador -i se a saída for a esperada.

A parte \(where\)\{0,1\} é um truque para simular um ? regex, que significa repetir 0 a 1 vezes, ganancioso.

    
por 06.01.2016 / 18:55