shell脚本中使用eval命令同时将一行文本的多个部分赋值给多个变量

- 脚本

编写shell脚本处理文本的时候,经常会遇到将文本多列数据赋值给不同的变量,最简单的方法是每次读取一行数据后,使用awk每次截取不同的位置,一行一个定义多个变量。但是如果要从每行中读取的数据多的时候,就要占用很多行去定义变量。这里记录下怎么使用 eval 命令一次定义多个变量使用awk不同位置的值。


示例数据

例如现在需要将下面的文本内容每行都转换为 json 格式,好传递给接口写入数据。

[root@imzcy ~]# cat example.txt
db001 order 50000
db001 logistics 50000
db001 sms 60000
db002 pay 10000
db002 history 300000
[root@imzcy ~]#

转换后样子

{"database":"db001","table":"order","line":50000}




传统定义多行变量

常规的方法就是使用while循环每次读取一行后,多行定义多个变量每次赋值一个。

[root@imzcy ~]# cat test-01.sh
#!/bin/bash
# auther: zcy
# site: https://www.imzcy.cn

data_file="/root/example.txt"

while read data
do

    database=$(echo "${data}" |awk '{print $1}')
    table=$(echo "${data}" |awk '{print $2}')
    line=$(echo "${data}" |awk '{print $3}')

    echo '{"database":"'"${database}"'","table":"'"${table}"'","line":'"${line}"'}'

done <${data_file}
[root@imzcy ~]#

执行输出

[root@imzcy ~]# sh test-01.sh
{"database":"db001","table":"order","line":50000}
{"database":"db001","table":"logistics","line":50000}
{"database":"db001","table":"sms","line":60000}
{"database":"db002","table":"pay","line":10000}
{"database":"db002","table":"history","line":300000}
[root@imzcy ~]#

确认json解析正常

[root@imzcy ~]# echo '{"database":"db001","table":"order","line":50000}' |jq .
{
  "database": "db001",
  "table": "order",
  "line": 50000
}
[root@imzcy ~]#




使用eval命令直接赋值多个变量

使用一行 eval 命令实现上面多行的效果

[root@imzcy ~]# cat test-02.sh
#!/bin/bash
# auther: zcy
# site: https://www.imzcy.cn

data_file="/root/example.txt"

while read data
do

    eval $(echo "${data}" |awk '{printf("database=%s; table=%s; line=%s",$1,$2,$3)}')

    echo '{"database":"'"${database}"'","table":"'"${table}"'","line":'"${line}"'}'

done <${data_file}
[root@imzcy ~]#

执行输出

[root@imzcy ~]# sh test-02.sh
{"database":"db001","table":"order","line":50000}
{"database":"db001","table":"logistics","line":50000}
{"database":"db001","table":"sms","line":60000}
{"database":"db002","table":"pay","line":10000}
{"database":"db002","table":"history","line":300000}
[root@imzcy ~]#

确认json解析正常

[root@imzcy ~]# echo '{"database":"db001","table":"order","line":50000}' |jq .
{
  "database": "db001",
  "table": "order",
  "line": 50000
}
[root@imzcy ~]#




eval 执行示例

在Linux中,eval命令用于将字符串作为命令执行。它接受一个字符串参数,并将其解析为可执行的命令。

如下所示,eval database=db001 的作用相当于就是直接执行了 database=db001 进行变量赋值。

[root@imzcy ~]# eval database=db001
[root@imzcy ~]# echo $database
db001
[root@imzcy ~]#

使用 awk 格式化输出

[root@imzcy ~]# echo "db001 order 50000" |awk '{printf("database=%s; table=%s; line=%s",$1,$2,$3)}'
database=db001; table=order; line=50000[root@imzcy ~]#
[root@imzcy ~]#

使用 eval 将封号分隔的多个字符串赋值同时定义为多个变量(多个字符串可以用封号或空格分隔)。

[root@imzcy ~]# unset database table line
[root@imzcy ~]# eval database=db001; table=order; line=50000
[root@imzcy ~]# echo $database
db001
[root@imzcy ~]# echo $table
order
[root@imzcy ~]# echo $line
50000
[root@imzcy ~]#