这是我的第一篇文章,我不知道在 StackExchage、Google、Wiki、GNU、Internet 之前我是如何管理任何东西的:)
我正在尝试找到一种方法来构建 SQL 数据库生成器 bash 脚本,目前看起来像这样......
renice -n 19 $$;
idx=32768;
dbt='Radix_en';
cat Domains_en.txt;
cat Tables_en.txt;
while read;
do
checks="$(echo -n $REPLY | md5sum)";
checks=${checks%" -"};
echo "insert into $dbt values ($idx,'$(uuidgen)','${checks}',$REPLY);";
idx=$((idx+1));
done < Data.txt;
echo "commit;";
数据来自Data.txt,目前的形式为:
'NUMBER','US_EN','LATIN','GREEK','GERMAN'
0,'zero','nulla','μηδέν','Null'
1,'one','Unum','ένα','ein'
输出是有效的 SQL(对于 Firebird):
create domain ...;
create domain ...;
commit;
create table ( ... );
create table ( ... );
commit;
insert into Radix_en values (32768,'dff0207a-591f-4435-9f8b-7b9b3e6ba2c1','d1f77359b3f7236806489ba3108c771f','NUMBER','US_EN','LATIN','GREEK','GERMAN');
insert into Radix_en values (32769,'5ef0e634-5c96-4ae4-92a8-0d68c02ffeb6','4e3f710600230cf0520bf32269511062',0,'zero','nulla','μηδέν','Null');
insert into Radix_en values (32770,'eae9cacc-3ee3-4471-afad-e5af201da435','9ab2f782988416431238ec63277b11df',1,'one','Unum','ένα','ein');
commit;
我想找到一种方法为每个字段生成 MD5 校验和,而不是生成包括分隔符的整行文本。
Data.txt 格式尚未最终确定,我可能会将其格式更改为任何使这成为可能或更容易的格式。
此外,如果必须有几个单独的步骤 - 很好,因为整个过程应该编写脚本并自动化。我正在考虑先处理 Data.txt,然后通过此脚本运行它,但我想尽可能简化该过程。不同的 Data.txt 文件的数量可能很大,而且我还有许多其他处理器需要包含。
事实上,我也在尝试了解有关 bash 脚本的更多信息,并且我更希望找到专家方法并为这个问题提供建议,而不是具体的解决方案。
我什至不确定我的帖子标题是否是我需要的解决方案,因此它与我的问题有关。我不确定是否应该将其发布在我经常访问的超级用户上或此处。所以我先在这里发帖,如果我有点偏离,抱歉。
谢谢!
桑德尔
... 于 08/23/2014 3:00 AM 编辑添加更多内容
感谢使用 IFS 的 mikeserv 正在工作,所以我的脚本现在如下所示:
renice -n 19 $$ > /dev/null; #for now
idx=32768;
dbt='Radix_en';
cat Domains_en.txt;
cat Tables_en.txt;
while read;
do
gid="$idx,'$(uuidgen)'";
IFS=,; set -f # no gobbling!
echo "insert into $dbt values ($gid";
for field in $REPLY
do
printf '%s' ",$field,'";
printf '%s' "$field" | md5sum;
done | cut -d\ -f1;
echo "$var);";
idx=$((idx+1));
done < Data.txt;
输出很棒,换行符使文本编辑/搜索变得更加容易,而 Firebird 仍然很高兴,除了一件事..
这是输出:
create domain ...;
create domain ...;
commit;
create table ( ... );
create table ( ... );
commit;
insert into Radix_en values (32768,'303f8957-57cf-4485-ace4-d21c7cf144e6'
,'NUMBER','722d79c16b51fe86610972b8d950038c
,'US_EN','b63fb39e32b062c76694bec58c4f8c67
,'LATIN','fd6f27a3c59111fc2a0b5e452595ef3d
,'GREEK','c081310697bb6b7d7bed5034824e2530
,'GERMAN','15db1d0e1b0861d8ac1f391db801493a
);
insert into Radix_en values (32769,'e7fdf095-d31c-4c59-a23b-7ea67db7aefb'
,0,'cfcd208495d565ef66e7dff9f98764da
,'zero','01b40535afbfd9611e910f58f4ab5146
,'nulla','584edd0b6638798dee53e2c23e84e2d1
,'μηδέν','cd3ed2f1039ed8668b4d48e742bd2e5b
,'Null','e0a93a9e6b0eb1688837d8bab9b4badb
);
insert into Radix_en values (32770,'a21916b5-2a05-4656-ad4e-c8cfee1abfcc'
,1,'c4ca4238a0b923820dcc509a6f75849b
,'one','7e31533231a12e4a560a18ac8cd02112
,'Unum','05d92bcbffbf59b375f25945e9af2dd0
,'ένα','826f5e2d5ba7ace48f4d6fe3c5e2925f
,'ein','dcc09a2cb665ca332d1689cb11aff592
);
commit;
md5 哈希末尾缺少分隔符,我不知道如何与管道协商输出。我在这里不明白是什么?
由于在这种特殊情况下,数据字段将保存可编程 IC 的代码,因此分隔符之间的校验和中不会接受额外的字符,到目前为止看起来是这样。同样,代码采用 ASCII 格式,而我的分隔符将不是 ASCII 的一部分,因此它是安全的。 Firebird 也会拒绝任何非 ASCII 的内容。
如果您能好心地告诉我如何完成这个脚本,因为我已经在努力解决 IFS 刚刚向我展示的一些新问题(是的,Windows 上的文件路径)。我将尝试看看这个脚本如何与纯 ASCII 一起工作,然后我想继续并就更多问题发表另一篇文章。
再次感谢你的帮助!
桑德尔
... 于 2014 年 8 月 30 日 7:00 PM 编辑至最终版本
用 sed 替换 cut 似乎可行。 Firebird 字段输入仍然需要转义分号 ('),并添加另一个相同的分号,并且数据文件中当前的逗号 IFS 分隔符仍然需要替换为非 ASCII。该脚本仍然是单文件输入,而不是递归文件列表。 echo 可能应该被 printf 取代,还有更多......
这是不包括 shebang 的最终脚本:
renice -n 19 $$ >> Radix_en_log.txt;
idx=32768; dbt='Radix_en';
cat Domains_en.txt; cat Tables_en.txt;
while read; do
gid="$idx,'$(uuidgen)'";
IFS=,; set -f;
echo "insert into $dbt values ($gid";
for field in $REPLY
do
printf '%s' ",$field,'"; printf '%s' "$field" | md5sum;
done | sed "s/[ ][ ][-]/\'/g"; printf '%s\n' ");";
idx=$((idx+1));
done < Data.txt;
echo "commit;";
这是输出:
create domain ...;
create domain ...;
commit;
create table ( ... );
create table ( ... );
commit;
insert into Radix_en values (32768,'2f675b86-b2b4-4e52-b000-e6a8cf0f3dca'
,'NUMBER','722d79c16b51fe86610972b8d950038c'
,'US_EN','b63fb39e32b062c76694bec58c4f8c67'
,'LATIN','fd6f27a3c59111fc2a0b5e452595ef3d'
,'GREEK','c081310697bb6b7d7bed5034824e2530'
,'GERMAN','15db1d0e1b0861d8ac1f391db801493a'
);
insert into Radix_en values (32769,'e2afcd65-9a1b-49e3-baf1-74b0619a4776'
,0,'cfcd208495d565ef66e7dff9f98764da'
,'zero','01b40535afbfd9611e910f58f4ab5146'
,'nulla','584edd0b6638798dee53e2c23e84e2d1'
,'μηδέν','cd3ed2f1039ed8668b4d48e742bd2e5b'
,'Null','e0a93a9e6b0eb1688837d8bab9b4badb'
);
insert into Radix_en values (32770,'f51b72eb-d64f-4e9e-ab49-8954df9505cd'
,1,'c4ca4238a0b923820dcc509a6f75849b'
,'one','7e31533231a12e4a560a18ac8cd02112'
,'Unum','05d92bcbffbf59b375f25945e9af2dd0'
,'ένα','826f5e2d5ba7ace48f4d6fe3c5e2925f'
,'ein','dcc09a2cb665ca332d1689cb11aff592'
);
commit;
谢谢!
桑德尔
答案1
shell 有一个内置的变量扩展字段分隔符。因此,如果你有一个字符串并且你的分隔符是固定的,你可以这样做:
var=32768,'dff0207a-591f-4435-9f8b-7b9b3e6ba2c1','d1f77359b3f7236806489ba3108c771f','NUMBER','US_EN','LATIN','GREEK','GERMAN'
( IFS=,; set -f
for field in $var
do printf '\n%s\n\t' "$field - md5:" >&2
printf %s "$field" |
md5sum
done |
cut -d\ -f1
)
32768 - md5:
f43764367fa4b73ba947fae71b0223a4
dff0207a-591f-4435-9f8b-7b9b3e6ba2c1 - md5:
0983e6c45209f390461c1b1df9320674
d1f77359b3f7236806489ba3108c771f - md5:
07d82ab57ba81f991ab996bd7c5a0441
NUMBER - md5:
34f55eca38e0605a84f169ff61a2a396
US_EN - md5:
c9d3e580b7b102e864d9aea8703486ab
LATIN - md5:
0e869135050d24ea6e7a30fc6edbac6c
GREEK - md5:
d4cacc28e56302bcec9d7af4bba8c9a7
GERMAN - md5:
ed73cca110623766d7a2457331a4f373
这应该会给你一个换行符分隔的 md5 列表 - 就像我一样。
IFS=,
用于指定当执行任何变量类型 shell 扩展时,shell 应将其拆分为字符,
而不是<space><newline><tab>
- 这是默认值。set -f
用于指定如果 shell 在未加引号的扩展中遇到任何文件 glob,则不应扩展它们 - 因此无论当前目录的内容如何,echo *
都只会打印。*
$var
对于shell中的每个逗号分隔字段printf "$field" | md5sum
,因此每个字段一次,没有分隔符字符串,正如我所理解的问题的意思。最后在收到它们时修剪每个输出行末尾的cut
几个空格和。-
大多数输出实际上是stderr
-cut
只见过md5sums
.