在 bash 脚本中对 $REPLY 中的字符串进行标记化

在 bash 脚本中对 $REPLY 中的字符串进行标记化

这是我的第一篇文章,我不知道在 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.

相关内容