Outra questão awk (ward) - mapeando substrings com multi-chaves

2

Eu tenho dois arquivos semelhantes a este:

mapping.txt :

100178  L08/2015
100180  L08/2015
103822  J03/2012
103823  A06/2012
103823  J02/2012
103823  J03/2012
...

input.txt :

100180011|225|
100180011|226|
100181111|201|
100181111|202|
103823004|011|
103823004|012|
...

Desejado output.txt em que se os primeiros 6 dígitos do arquivo de entrada corresponderem a uma ou mais entradas do arquivo de mapeamento, imprima a terceira coluna como a segunda coluna do arquivo de mapeamento, caso contrário, coloque "B00 / 0000":

100180011|225|L08/2015
100180011|226|L08/2015  
100181111|201|B00/0000
100181111|202|B00/0000
103823004|011|A06/2012
103823004|011|J02/2012
103823004|011|J03/2012
103823004|012|A06/2012
103823004|012|J02/2012
103823004|012|J03/2012

Idealmente, isso deve funcionar no OSX, mas também tenho acesso a uma caixa do Linux.

    
por K - 19.06.2015 / 17:13

2 respostas

4

Assumindo bash e assumindo que ambos os arquivos estão classificados:

join -a1 <(sed 's/./& /6' input.txt) mapping.txt | sed 's/ //g; s/|$/|B00\/0000/'

Saída:

100180011|225|L08/2015
100180011|226|L08/2015
100181111|201|B00/0000
100181111|202|B00/0000
103823004|011|A06/2012
103823004|011|J02/2012
103823004|011|J03/2012
103823004|012|A06/2012
103823004|012|J02/2012
103823004|012|J03/2012

Não há awk à vista, desculpe. :)

Editar: explicação:

  • sed 's/./& /6' - adiciona um espaço após o sexto caractere em cada linha, então a saída é 100180 011|225|L08/2015
  • join -a1 une os arquivos na primeira coluna; -a1 informa join para deixar as linhas inalteradas inalteradas do primeiro arquivo
  • sed 's/ //g;' - remove os espaços no resultado
  • ... 's/|$/|B00\/0000/' - adiciona /|B00/0000 às linhas que terminam com | , ou seja, às linhas não correspondentes do primeiro arquivo.
por 19.06.2015 / 17:36
2

Você pode tentar seguir awk :

awk 'NR == FNR { k = substr($1, 1, 6); x[$1,$2] = k; y[$1,$2] = 0; next; } { for (i in x) { if (x[i] == $1) { split(i, t, SUBSEP); print t[1] "|" t[2] "|" $2; y[i] = 1; } } } END { for (i in y) if (y[i] == 0) { split(i, t, SUBSEP); print t[1] "|" t[2] "|B00/0000" } }' FS="|" input.txt FS=" " mapping.txt

O resultado deve ser:

100180011|225|L08/2015
100180011|226|L08/2015
103823004|011|A06/2012
103823004|012|A06/2012
103823004|011|J02/2012
103823004|012|J02/2012
103823004|011|J03/2012
103823004|012|J03/2012
100181111|201|B00/0000
100181111|202|B00/0000
    
por 19.06.2015 / 17:31