fonte de vários arquivos e saída de um arquivo

3

Eu tenho um nome de arquivo "conf1" contendo variáveis como:

name='john'
last=''
custom='1000'

e outro nome de arquivo conf2 assim:

name='john'
last='star'

Eu quero mesclar entre eles para um arquivo, mas de uma maneira que o arquivo mesclado contenha a variável na mesma ordem que eu os forneço.

por exemplo, se eu fonte conf1 e, em seguida, conf2, a variável de conf 2 sobrescreverá conf1. mas também terei a variável que não tenho em conf2.

Eu quero mesclar e criar um arquivo de ambos com apenas as variáveis que são exclusivas e as últimas fontes.

saída exigida: conf3

name='john'
last='star'
custom='1000'

isso é possível?

    
por Asaf Magen 28.05.2015 / 12:19

5 respostas

3

Você poderia fazer:

$ awk -F= '{l[$1]=$0};END{for (i in l) print l[i]}' conf1 conf2
custom='1000'
last='star'
name='john'

Observe que a ordem das linhas na saída não é garantida (com base em como awk armazena a matriz internamente em uma tabela de hash), mas as configurações em conf2 substituem as em conf1 .

onde

  • awk -F= ... conf1 conf2 call awk com = como separador em arquivos conf.
  • {l[$1]=$0} armazena a definição de cada var, a mais nova sobreposta a mais antiga
  • END{ ... } no final (depois de todos os arquivos processados)
  • for (i in l) loop para todos os var,
  • print l[i] e imprimi-lo.
por 28.05.2015 / 12:54
1

Você pode usar join para mesclar os dois arquivos e preservar a ordem das chaves. Aqui está um exemplo:
conf1 :

name='john'
last=''
custom='1000'
rule='default'

conf2 :

name='joe'
second='none'
fourth='dash'
last='star'
rule='whatever'

se você executar:

{ { join -t= -1 2 -2 1 -o 1.1 1.2 2.2 <(sort -t= -k2,2 <(nl -ba -nrz -s= conf1)) \
<(sort -t= -k1,1 conf2); join -t= -1 2 -2 1 -v1 -o 1.1 1.2 1.3 \
<(sort -t= -k2,2 <(nl -ba -nrz -s= conf1)) <(sort -t= -k1,1 conf2); \
} | sort -k1,1n | cut -d= -f2-; join -t= -1 1  -2 2 -v2 -o 2.1 2.2 2.3 \
<(sort -t= -k1,1 conf1) <(sort -t= -k2,2 <(nl -ba -nrz -s= conf2)) \
| sort -k1,1n | cut -d= -f2-; } > merged_conf

o conteúdo de merged_conf é:

name='joe'
last='star'
custom='1000'
rule='whatever'
second='none'
fourth='dash'

Talvez seja mais fácil entender se estiver trabalhando com dois arquivos temporários. Primeiro n umber as l ines em conf1 e conf2 e sort delas por 2 nd campo:

sort -t= -k2,2 <(nl -ba -nrz -s= conf1) >conf1.sorted
sort -t= -k2,2 <(nl -ba -nrz -s= conf2) >conf2.sorted

acima, cria conf1.sorted :

000003=custom='1000'
000002=last=''
000001=name='john'
000004=rule='default'

e conf2.sorted :

000003=fourth='dash'
000004=last='star'
000001=name='joe'
000005=rule='whatever'
000002=second='none'

Agora, o mesmo comando usando os arquivos originais e os arquivos numerados / classificados:

{ { join -t= -1 2 -2 1 -o 1.1 1.2 2.2 conf1.sorted <(sort -t= -k1,1 conf2); \
join -t= -1 2 -2 1 -v1 -o 1.1 1.2 1.3 conf1.sorted \
<(sort -t= -k1,1 conf2); } | sort -k1,1n | cut -d= -f2-; \
join -t= -1 1  -2 2 -v2 -o 2.1 2.2 2.3 <(sort -t= -k1,1 conf1) conf2.sorted \
| sort -k1,1n | cut -d= -f2-; } > merged_conf

Explicação:

join -t= -1 2 -2 1 -o 1.1 1.2 2.2 conf1.sorted <(sort -t= -k1,1 conf2)

une os arquivos com base no campo 2 de conf1.sorted e campo 1 de conf2 imprimindo as linhas comuns, mas com os valores ( 2.2 ) de conf2 :

000002=last='star'
000001=name='joe'
000004=rule='whatever

e

join -t= -1 2 -2 1 -v1 -o 1.1 1.2 1.3 conf1.sorted <(sort -t= -k1,1 conf2)

imprime as linhas não parciais de conf1.sorted :

000003=custom='1000'

eles são agrupados em {..} e a saída é canalizada para sort -k1,1n | cut -d= -f2- para restaurar a ordem das chaves do original conf1 :

name='joe'
last='star'
custom='1000'
rule='whatever'

então

join -t= -1 1  -2 2 -v2 -o 2.1 2.2 2.3 <(sort -t= -k1,1 conf1) conf2.sorted

junta-se com base no campo 1 de conf1 e campo 2 de conf2.sorted imprimindo linhas não parciais do último:

000003=fourth='dash'
000002=second='none'

da mesma maneira, a saída é canalizada para sort -k1,1n | cut -d= -f2- para restaurar a ordem das chaves do original conf2 :

second='none'
fourth='dash'

Agrupar todos os itens acima produz a saída desejada:

name='joe'
last='star'
custom='1000'
rule='whatever'
second='none'
fourth='dash'

isso é redirecionado ( > ) para merged_conf . Por fim, remova os arquivos classificados:

rm conf{1,2}.sorted

Isso pode ser repetido para arquivos de configuração adicionais usando merged_conf e, por exemplo, conf3 como argumentos e assim por diante ...

    
por 28.05.2015 / 20:11
0

Uma abordagem Perl:

$ perl -F= -lane '$k{$F[0]}=$F[1]; END{print "$_=$k{$_}" for keys(%k)}' conf1 conf2 
last='star'
name='john'
custom='1000'

Esta é a mesma ideia da resposta de Stéphane. Ele cria um hash em que o nome da variável é a chave e seu valor é o valor. Então, uma vez que todos os arquivos foram processados, ele imprime os pares chave / valor. Observe que a ordem das linhas não é garantida e pode mudar entre invocações, mas os valores de conf2 sempre substituirão os de conf1 .

    
por 28.05.2015 / 16:10
0

Para que conf2 tenha prioridade, ele deve preceder conf1 em sort args.

sort -suk1,1 -t= conf2 conf1 | tac

Saída:

name='john'
last='star'
custom='1000'

O texto acima se baseia no fato de que as etiquetas custom , last e name são classificadas apropriadamente para sua ordem de saída exigida. No entanto, quando os rótulos são nomeados, esse mod funcionará:

eval srx=\" 's/^'{name/1,last/2,custom/3}'=&/;' \"   # sort seq: 1,2,3,etc
sort -suk1,1 -t= conf2 conf1 | sed "$srx" | sort -n | cut -d= -f2-    
    
por 28.05.2015 / 18:32
-1

Use isto:

name=${name:-John}
last=${last:-}
custom=${custom:-1000}

... e similarmente no outro arquivo. Leia a página de manual do seu shell. Isso definirá as variáveis para os valores especificados, a menos que elas já estejam definidas e não sejam nulas. Não importará a ordem de origem dos arquivos, pelo menos não com os dados de exemplo que você mostrou.

    
por 28.05.2015 / 12:42