如何评估或处理数据中的if语句?
How to evaluate or process if statements in data?
背景
我写了一个 bash 脚本,它从 PostgreSQL 数据库中提取简单的用户函数,使用 awk 将 pgplsql 命令转换为 SQL(比如 PERFORM function()
到 SELECT function()
, 删除注释 --.*
, 等), 将 SQL 命令存储到文件 (file.sql
) 并在数据库中读取和执行它们:
$ psql ... -f file.sql db
功能简单,主要是调用其他用户定义的功能。但是如何 "evaluate" 或处理 IF
语句?:
IF = 'customer1' THEN -- THESE MEANS ARGUMENT TO PGPL/SQL FUNCTION
PERFORM subfunction1(); -- THAT THIS IF STATEMENT IS IN:
ELSE -- SELECT function('customer1');
PERFORM subfunction2(); -- = 'customer1'
END IF;
Tl;博士:
IF
s 等不是 SQL,因此应使用 awk 对其进行预评估。可以安全地假设上面已经处理成一条记录并删除了注释:
IF = 'customer1' THEN PERFORM subfunction1(); ELSE PERFORM subfunction2(); END IF;
上面"evaluating"之后应该替换为:
SELECT subfunction1('customer1');
如果评估它的 awk 被调用:
$ awk -v arg1="customer1' -f program.awk file.sql
或者如果 arg1
是其他任何东西,例如 customer2
:
SELECT subfunction2('customer2');
编辑
expr
醒来的第一件事就是:
$ awk -v arg="'customer1'" '
{
gsub(/$1/,arg) # replace func arg with string
n=split([=16=],a,"(IF|THEN|ELSE|ELSE?IF|END IF;)",seps) # seps to get ready for SQL CASE
if(seps[1]=="IF") {
# here should be while for ELSEIF
c="expr " a[2]; c|getline r; close(c) # use expr to solve
switch (r) { # expr has 4 return values
case "1": # match
print a[3]
break
case "0": # no match
print a[4]
break
default: # (*) see below
print r
exit # TODO
} } }' file.sql
(*) expr
输出 0,1,2 或 3:
$ expr 1 = 1
1
$ expr 1 = 2
0
但是,如果省略空格:
$ expr 1=1
1=1
无需编写完整的语言解析器,如果您正在寻找便宜又令人愉快的东西,那么这可能是一个不错的起点:
$ cat tst.awk
{ gsub(/$1/,"7"arg1"7") }
match([=10=],/^IF\s+(\S+)\s+(\S+)\s+(\S+)\s+THEN\s+(\S+)\s+(\S+)\s+ELSE\s+(\S+)\s+(\S+)\s+END\s+IF/,a) {
lhs = a[1]
op = a[2]
rhs = a[3]
trueAct = (a[4] == "PERFORM" ? "SELECT" : a[4]) FS a[5]
falseAct = (a[6] == "PERFORM" ? "SELECT" : a[6]) FS a[7]
if (op == "=") {
print (lhs == rhs ? trueAct : falseAct)
}
}
$ awk -v arg1='customer1' -f tst.awk file
SELECT subfunction1('customer1');
$ awk -v arg1='bob' -f tst.awk file
SELECT subfunction2('bob');
以上使用 GNU awk 作为第三个参数来匹配 ()。希望它足够容易理解,您可以根据需要进行按摩以处理其他结构或该结构的其他变体。
背景
我写了一个 bash 脚本,它从 PostgreSQL 数据库中提取简单的用户函数,使用 awk 将 pgplsql 命令转换为 SQL(比如 PERFORM function()
到 SELECT function()
, 删除注释 --.*
, 等), 将 SQL 命令存储到文件 (file.sql
) 并在数据库中读取和执行它们:
$ psql ... -f file.sql db
功能简单,主要是调用其他用户定义的功能。但是如何 "evaluate" 或处理 IF
语句?:
IF = 'customer1' THEN -- THESE MEANS ARGUMENT TO PGPL/SQL FUNCTION
PERFORM subfunction1(); -- THAT THIS IF STATEMENT IS IN:
ELSE -- SELECT function('customer1');
PERFORM subfunction2(); -- = 'customer1'
END IF;
Tl;博士:
IF
s 等不是 SQL,因此应使用 awk 对其进行预评估。可以安全地假设上面已经处理成一条记录并删除了注释:
IF = 'customer1' THEN PERFORM subfunction1(); ELSE PERFORM subfunction2(); END IF;
上面"evaluating"之后应该替换为:
SELECT subfunction1('customer1');
如果评估它的 awk 被调用:
$ awk -v arg1="customer1' -f program.awk file.sql
或者如果 arg1
是其他任何东西,例如 customer2
:
SELECT subfunction2('customer2');
编辑
expr
醒来的第一件事就是:
$ awk -v arg="'customer1'" '
{
gsub(/$1/,arg) # replace func arg with string
n=split([=16=],a,"(IF|THEN|ELSE|ELSE?IF|END IF;)",seps) # seps to get ready for SQL CASE
if(seps[1]=="IF") {
# here should be while for ELSEIF
c="expr " a[2]; c|getline r; close(c) # use expr to solve
switch (r) { # expr has 4 return values
case "1": # match
print a[3]
break
case "0": # no match
print a[4]
break
default: # (*) see below
print r
exit # TODO
} } }' file.sql
(*) expr
输出 0,1,2 或 3:
$ expr 1 = 1
1
$ expr 1 = 2
0
但是,如果省略空格:
$ expr 1=1
1=1
无需编写完整的语言解析器,如果您正在寻找便宜又令人愉快的东西,那么这可能是一个不错的起点:
$ cat tst.awk
{ gsub(/$1/,"7"arg1"7") }
match([=10=],/^IF\s+(\S+)\s+(\S+)\s+(\S+)\s+THEN\s+(\S+)\s+(\S+)\s+ELSE\s+(\S+)\s+(\S+)\s+END\s+IF/,a) {
lhs = a[1]
op = a[2]
rhs = a[3]
trueAct = (a[4] == "PERFORM" ? "SELECT" : a[4]) FS a[5]
falseAct = (a[6] == "PERFORM" ? "SELECT" : a[6]) FS a[7]
if (op == "=") {
print (lhs == rhs ? trueAct : falseAct)
}
}
$ awk -v arg1='customer1' -f tst.awk file
SELECT subfunction1('customer1');
$ awk -v arg1='bob' -f tst.awk file
SELECT subfunction2('bob');
以上使用 GNU awk 作为第三个参数来匹配 ()。希望它足够容易理解,您可以根据需要进行按摩以处理其他结构或该结构的其他变体。