在 bash 脚本中标记来自 $REPLY 的字符串

arc*_*bit 3 shell-script text-processing

这是我的第一篇文章,我不知道在 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;";
Run Code Online (Sandbox Code Playgroud)

数据来自Data.txt,目前格式为:

'NUMBER','US_EN','LATIN','GREEK','GERMAN'
0,'zero','nulla','?????','Null'
1,'one','Unum','???','ein'
Run Code Online (Sandbox Code Playgroud)

输出是有效的 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;
Run Code Online (Sandbox Code Playgroud)

我想找到一种方法来为每个字段生成 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;
Run Code Online (Sandbox Code Playgroud)

输出很棒,换行符使文本编辑/搜索变得更加容易,而 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;
Run Code Online (Sandbox Code Playgroud)

md5 哈希在末尾缺少分隔符,我不知道如何与管道协商输出。我在这里不明白什么?

由于在这种特殊情况下,数据字段将保存可编程 IC 的代码,因此在分隔符之间的校验和中不会接受额外的字符,到目前为止看起来是这样。同样,代码是 ASCII 的,我的分隔符不是 ASCII 的一部分,所以它是安全的。Firebird 也会拒绝任何非 ASCII 的内容。

如果您能指点我如何完成这个脚本,我已经开始思考 IFS 刚刚向我展示的一些新问题(是的,Windows 上的文件路径)。我会尝试看看这个脚本如何与纯 ASCII 一起工作,然后我想继续写一篇关于更多问题的帖子。

再次感谢你的帮助!

桑多

... 于 08/30/2014 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;";
Run Code Online (Sandbox Code Playgroud)

这是输出:

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;
Run Code Online (Sandbox Code Playgroud)

谢谢!

桑多

mik*_*erv 5

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
Run Code Online (Sandbox Code Playgroud)

这应该给你一个换行符分隔的 md5s 列表 - 就像我一样。

IFS=,用于指定当执行任何变量类型的外壳扩展时,外壳应将其拆分为,字符而不是<space><newline><tab>- 这是默认值。set -f用于指定如果 shell 在未加引号的扩展中遇到任何文件 glob,它不应该扩展它们 - 因此echo *只打印*而不考虑当前目录的内容。

对于$varshell 中的每个逗号分隔字段printf "$field" | md5sum- 所以每个字段一次没有分隔符字符串,因为我认为这个问题是这个意思。最后在接收到它们时cut修剪-每个输出行末尾的几个空格和。大多数输出​​实际上是stderr-cut只看到md5sums.