通过 awk / xargs 替换定义字符串中的变量值
Replacing variable values in defined string through awk / xargs
我们在bash中动态生成一个字符串,用于将数据插入到oracle数据库中。字符串就像
> echo $str1
insert into tbl select '$jobid','','','','$sdate' from dual ;
这里变量 $1,$2 ... 是动态的,最多可以达到 10
现在我们在一个文件中拥有与上面字符串中的数字变量 ($1,$2..) 相同数量的“:”分隔数据列的数据。
这里的挑战是将 $1 替换为第一列数据,将 $2 替换为第二列,依此类推。这需要对数据集的所有行完成,并且需要以 "insert" 字符串作为基础并使用文件中的替换数据生成一个单独的文件。
例如样本数据
cat test.dat
ONLINE:odr1_redo_06a.log:NO
ONLINE:odr1_redo_06b.log:NO
ONLINE:odr1_redo_05a.log:NO
and the string is
echo $str1
insert into tbl select '$jobid','','','','$sdate' from dual ;
要求的输出应该是
insert into tbl select '$jobid','ONLINE','odr1_redo_06a.log','NO','$sdate' from dual ;
insert into tbl select '$jobid','ONLINE','odr1_redo_06b.log','NO','$sdate' from dual ;
insert into tbl select '$jobid','ONLINE','odr1_redo_05a.log','NO','$sdate' from dual ;
尝试在 awk 中使用字符串作为外部变量。运气不好
cat test.dat | awk -F: -v var="$str1" '{print var}'
insert into tbl select '$jobid','','','','$sdate' from dual ;
insert into tbl select '$jobid','','','','$sdate' from dual ;
insert into tbl select '$jobid','','','','$sdate' from dual ;
or xargs
sed 's/:/ /g' test.dat | xargs -n3 bash -c "echo $str1"
insert into tbl select $jobid,,,,$sdate from dual
insert into tbl select $jobid,,,,$sdate from dual
insert into tbl select $jobid,,,,$sdate from dual
编写一个小循环并逐行调用会产生开销,所以不要这样做。知道如何以最佳方式做到这一点吗?
使用 Awk,对于每条记录,通过 gsub
函数将每个文字 $n 替换为模板中第 n 个字段的值并打印结果。
awk -F: -v tmpl="$str1" '{
out = tmpl
for (i=1; i<=NF; i++)
gsub(("\$" i), $i, out)
print out
}' file
概念验证:
$ str1="insert into tbl select '$jobid','$1','$2','$3','$sdate' from dual ;"
$
$ awk -F: -v tmpl="$str1" '{
> out = tmpl
> for (i=1; i<=NF; i++)
> gsub(("\$" i), $i, out)
> print out
> }' file
insert into tbl select '$jobid','ONLINE','odr1_redo_06a.log','NO','$sdate' from dual ;
insert into tbl select '$jobid','ONLINE','odr1_redo_06b.log','NO','$sdate' from dual ;
insert into tbl select '$jobid','ONLINE','odr1_redo_05a.log','NO','$sdate' from dual ;
我们在bash中动态生成一个字符串,用于将数据插入到oracle数据库中。字符串就像
> echo $str1
insert into tbl select '$jobid','','','','$sdate' from dual ;
这里变量 $1,$2 ... 是动态的,最多可以达到 10
现在我们在一个文件中拥有与上面字符串中的数字变量 ($1,$2..) 相同数量的“:”分隔数据列的数据。
这里的挑战是将 $1 替换为第一列数据,将 $2 替换为第二列,依此类推。这需要对数据集的所有行完成,并且需要以 "insert" 字符串作为基础并使用文件中的替换数据生成一个单独的文件。
例如样本数据
cat test.dat
ONLINE:odr1_redo_06a.log:NO
ONLINE:odr1_redo_06b.log:NO
ONLINE:odr1_redo_05a.log:NO
and the string is
echo $str1
insert into tbl select '$jobid','','','','$sdate' from dual ;
要求的输出应该是
insert into tbl select '$jobid','ONLINE','odr1_redo_06a.log','NO','$sdate' from dual ;
insert into tbl select '$jobid','ONLINE','odr1_redo_06b.log','NO','$sdate' from dual ;
insert into tbl select '$jobid','ONLINE','odr1_redo_05a.log','NO','$sdate' from dual ;
尝试在 awk 中使用字符串作为外部变量。运气不好
cat test.dat | awk -F: -v var="$str1" '{print var}'
insert into tbl select '$jobid','','','','$sdate' from dual ;
insert into tbl select '$jobid','','','','$sdate' from dual ;
insert into tbl select '$jobid','','','','$sdate' from dual ;
or xargs
sed 's/:/ /g' test.dat | xargs -n3 bash -c "echo $str1"
insert into tbl select $jobid,,,,$sdate from dual
insert into tbl select $jobid,,,,$sdate from dual
insert into tbl select $jobid,,,,$sdate from dual
编写一个小循环并逐行调用会产生开销,所以不要这样做。知道如何以最佳方式做到这一点吗?
使用 Awk,对于每条记录,通过 gsub
函数将每个文字 $n 替换为模板中第 n 个字段的值并打印结果。
awk -F: -v tmpl="$str1" '{
out = tmpl
for (i=1; i<=NF; i++)
gsub(("\$" i), $i, out)
print out
}' file
概念验证:
$ str1="insert into tbl select '$jobid','$1','$2','$3','$sdate' from dual ;"
$
$ awk -F: -v tmpl="$str1" '{
> out = tmpl
> for (i=1; i<=NF; i++)
> gsub(("\$" i), $i, out)
> print out
> }' file
insert into tbl select '$jobid','ONLINE','odr1_redo_06a.log','NO','$sdate' from dual ;
insert into tbl select '$jobid','ONLINE','odr1_redo_06b.log','NO','$sdate' from dual ;
insert into tbl select '$jobid','ONLINE','odr1_redo_05a.log','NO','$sdate' from dual ;