String de token de $ REPLY no script bash

3

Esta é minha primeira postagem, e não tenho ideia de como gerenciei nada antes do StackExchage, Google, Wiki, GNU, Internet, a lista continua:)

Estou tentando encontrar uma maneira de construir um script bash do gerador de banco de dados SQL, que atualmente se parece com isso ...

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;";

Os dados vêm do Data.txt, atualmente na forma de:

'NUMBER','US_EN','LATIN','GREEK','GERMAN'
0,'zero','nulla','μηδέν','Null'
1,'one','Unum','ένα','ein'

A saída é SQL válida (para o 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;

Eu gostaria de encontrar uma maneira de gerar a soma de verificação MD5 para cada campo, em vez de toda a linha de texto, incluindo os delimitadores.

O formato Data.txt ainda não está finalizado, e posso alterar seu formato para qualquer coisa que torne isso possível ou mais fácil.

Além disso, se houver várias etapas separadas - tudo bem, já que todo o processo deve ser roteirizado e automatizado. Eu estava considerando o processamento do Data.txt primeiro, depois executei esse script, mas gostaria de simplificar o processo o máximo possível. O número de diferentes arquivos Data.txt pode ser grande, e eu ainda tenho vários outros processadores para incluir.

Na verdade, também estou tentando aprender mais sobre scripts de bash, e estou bastante empenhado em encontrar uma abordagem especializada e aconselhar esse problema mais do que uma solução específica.

Nem sei se o título do meu post é a solução de que preciso e, portanto, está relacionado à minha pergunta. Eu não tinha certeza se deveria postar isso no Superusuário onde eu costumo visitar ou aqui. Então eu postei aqui primeiro, e desculpe se estou um pouco atrasado.

Obrigado!

Sandor

Editado para incluir mais em 08/23/2014 3:00 AM

Graças ao mikeserv usando o IFS está funcionando, então meus scripts agora se parecem com isso:

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;

A saída é ótima, as quebras de linha tornam a edição / busca de texto muito mais fácil, enquanto o Firebird ainda está feliz, exceto uma coisa.

Aqui está a saída:

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;

O hash md5 está faltando um delimitador no final, e não tenho idéia de como negociar a saída com os pipes. O que é que eu não estou entendendo aqui?

Como neste caso em particular os campos de dados vão conter código para ICs programáveis, nenhum caractere extra será aceitável na soma de verificação entre os delimitadores, e até agora parece que sim. Novamente, o código está em ASCII e meu delimitador será algo que não faz parte do ASCII, portanto, é seguro. Firebird também vai rejeitar qualquer coisa que não seja ASCII.

Se você fosse gentil em me indicar como terminar esse script, já estou batendo cabeça contra alguns novos problemas que o IFS acabou de me mostrar (sim, caminhos de arquivo no Windows). Vou tentar ver como esse script vai funcionar com ASCII puro, então eu gostaria de seguir em frente e fazer outro post sobre mais algumas questões.

Obrigado novamente por sua ajuda!

Sandor

Editado para final em 30/08/2014, 19:00

Substituir o corte por sed parece funcionar. A entrada do campo Firebird ainda precisa ser escapada por ponto-e-vírgula (') com outra soma igual, e o delimitador IFS da vírgula atual nos arquivos de dados ainda precisa ser substituído por não-ASCII. Em vez de listas de arquivos recursivas, esse script ainda é uma entrada de arquivo único. echo provavelmente deve ser substituído por printf, e muito mais ...

Aqui está o script final, excluindo o 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;";

Aqui está a saída:

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;

Obrigado!

Sandor

    
por arch-abit 22.08.2014 / 19:46

1 resposta

4

O shell possui um separador de campo de expansão variável integrado. Então, se você tem uma string e seu delimitador é sólido, você pode fazer:

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

Isso deve lhe dar uma lista separada por novas linhas de md5s - como aconteceu comigo.

IFS=, é usado para especificar que quando qualquer expansão de shell do tipo de variável é executada, o shell deve dividi-lo no caractere , em vez de <space><newline><tab> - que é o padrão. set -f é usado para especificar que, se o shell encontrar quaisquer globs de arquivo em uma expansão sem aspas, ele não deverá expandi-los - portanto, echo * imprimirá apenas * , independentemente do conteúdo do diretório atual.

Para cada campo separado por vírgula em $var , o shell faz printf "$field" | md5sum - então, uma vez por campo, sem sequências de separação, como eu entendo a pergunta. E o último cut apara os poucos espaços e o - no final de cada linha de saída, à medida que os recebe. A maior parte da saída é, na verdade, para stderr - cut , e só vê o md5sums .

    
por 22.08.2014 / 20:55