shell 从字符串中提取单词并将其分配给UNIX变量

9nvpjoqh  于 2023-10-23  发布在  Shell
关注(0)|答案(4)|浏览(116)

我有一个自动化的想法。以下是全部细节。每个用户发送给我一个SQL查询,然后我需要使用自动化脚本执行下面的步骤。
1.使用Unix shell脚本运行UNIX服务器中存在的SQL查询file.sql。

select count(*) as cnt from emp where employee='Scott' and job='Manager' and Salary>10000 and location='Chicago' and deptno=10 and hike_in_perc=15 and deptname is not null;

将查询输出放入UNIX变量。
1.如果count > 0,则退出。
1.如果count =0,那么我需要根据用户自动给出的where子句值更新Input表emp数据。(所以如果我重新运行上面的查询,我会得到count >0)。
我的目标是,当我运行用户给出的SQL查询时,应该得到记录计数>0。要实现这一点,请使用WHERE子句中提到的硬编码值更新输入表。

update emp set employee='Scott',job='Manager',Salary=10001(need to manipulate*),location='Chicago',deptno=10,hike_in_perc=15,deptname='ABC'(need to manipulate if value is not NULL*);

1.再次运行SQL查询,确保count >0。
下面的查询涉及到步骤3,我已经开始工作的自动化.
我有一个文本文件(cols.txt),其中包含的数据(制表符分隔符)如下。

employee='Scott' job='Manager' Salary=10000 location='Chicago' deptno=10
hike_in_perc=15 deptname='Accounts'

文件包含col_name=Value,列数不受限制,并且具有多个具有不同列数及其值的文件。
请问你可以帮助我如何提取每个列值沿着列名称一样:

var1=employee='Scott'
var2=job='Manager'
.....etc

我的最终目标是在SQL查询的UPDATE语句中使用这些值。请给我一个好的方法来实现这一点。先谢谢你。
我试过使用CUT和SED,但没有帮助,也没有得到预期的结果。

lyfkaqu1

lyfkaqu11#

如果我理解你的意图,可能比你想的要简单。
您可以通过将制表符替换为逗号来使用几乎“原样”的数据,* 假设您要添加一个WHERE子句 。显然, 永远不要 * 更新没有WHERE的表;我添加了一个简单的占位符。

$: cat file
employee='Scott'        job='Manager'   Salary=10000    location='Chicago'      deptno=10       hike_in_perc=15 deptname='Accounts'
employee='bob'  job='peon'      Salary=100      location='hell' deptno=666      hike_in_perc=1  deptname='drudgery'

$: while IFS=$'\t' read -r line; do echo "UPDATE sometable SET $line WHERE somecondition='$somevalue';";done < <( tr $'\t' , < file )
UPDATE sometable SET employee='Scott',job='Manager',Salary=10000,location='Chicago',deptno=10,hike_in_perc=15,deptname='Accounts' WHERE somecondition='foo';
UPDATE sometable SET employee='bob',job='peon',Salary=100,location='hell',deptno=666,hike_in_perc=1,deptname='drudgery' WHERE somecondition='foo';

$: while IFS=$'\t' read -r line; do echo "UPDATE sometable SET ${line//$'\t'/,} WHERE somecondition='$somevalue';";done<file
UPDATE sometable SET employee='Scott',job='Manager',Salary=10000,location='Chicago',deptno=10,hike_in_perc=15,deptname='Accounts' WHERE somecondition='bar';
UPDATE sometable SET employee='bob',job='peon',Salary=100,location='hell',deptno=666,hike_in_perc=1,deptname='drudgery' WHERE somecondition='bar';

例如,如果您的前两个字段是您的条件...

$: while IFS=$'\t' read -r a b new; do echo "UPDATE sometable SET ${new//$'\t'/,} WHERE $a AND $b;";done<file
UPDATE sometable SET Salary=10000,location='Chicago',deptno=10,hike_in_perc=15,deptname='Accounts' WHERE employee='Scott' AND job='Manager';
UPDATE sometable SET Salary=100,location='hell',deptno=666,hike_in_perc=1,deptname='drudgery' WHERE employee='bob' AND job='peon';

对于大型数据集,使用awk会更快。

$: awk -F$'\t' '{printf "UPDATE sometable SET "; for(i=3;i<NF;i++)printf "%s,",$i; print $NF " WHERE " $1 " AND " $2 ";"}' file
UPDATE sometable SET Salary=10000,location='Chicago',deptno=10,hike_in_perc=15,deptname='Accounts' WHERE employee='Scott' AND job='Manager';
UPDATE sometable SET Salary=100,location='hell',deptno=666,hike_in_perc=1,deptname='drudgery' WHERE employee='bob' AND job='peon';

这些做了很多假设,比如文件的每一行都是更新一条记录所需的所有数据-但我认为这是值得一提的,以防这更像是一个XY problem
如果你的文件可以是多行,但每个文件都是一个可能的UPDATE,那么也许另一种方法-

$: cat f2
employee='Scott'    job='Manager'
Salary=10000    location='New York' deptno=10
hike_in_perc=15 deptname='Accounts'

$: conditions="$(<f2)"
$: echo "select count(*) as cnt from emp where ${conditions//[$'\n\t']/ AND };"
select count(*) as cnt from emp where employee='Scott' AND job='Manager' AND Salary=10000 AND location='New York' AND deptno=10 AND hike_in_perc=15 AND deptname='Accounts';

祝你好运

yk9xbfzb

yk9xbfzb2#

awk

$ awk 'BEGIN{c=0}{for (i=1; i<=NF; i++) print "var"++c"="$i}' cols.txt
var1=employee='Scott'
var2=job='Manager'
var3=Salary=10000
var4=location='Chicago'
var5=deptno=10
var6=hike_in_perc=15
var7=deptname='Accounts'
xwbd5t1u

xwbd5t1u3#

下面的脚本将解析文件声明的变量。

for var in $(cat cols.txt);do declare "$var"; done

[~] echo $employee
'Scott'
[~] echo $job
'Manager'
[~] echo $Salary
10000
[~] echo $location
'Chicago'
[~] echo $deptno
10
[~] echo $hike_in_perc
15
[~] echo $deptname
'Accounts'
s3fp2yjn

s3fp2yjn4#

不要填充一堆后缀为1-N的标量变量,填充一个数组,例如。arr[1]="employee='Scott'",关联数组可能最适合您的需要,arr['employee']='Scott'。在这个论坛和stackexchange上有很多答案,展示了如何做到这两点,但你的答案有点复杂,因为每行有多个制表符分隔的赋值,所以你可以这样做:

declare -A arr
while IFS='=' read -r tag val; do
    arr["$tag"]="$val"
done < <(tr $'\t' $'\n' < file)

结果是arr[]被填充了标签(名称)到值的Map:

declare -p arr
declare -A arr=([employee]="'Scott'" [job]="'Manager'" [deptno]="10" [location]="'Chicago'" [deptname]="'Accounts'" [hike_in_perc]="15" [Salary]="10000" )

上面假设输入中没有重复的标记,因为OP提供的示例中没有。

相关问题