tr -d \n <infile | tr \~ \n | paste -d~ - - - - - - - - - - - - - -
Isso vai funcionar.
Estamos usando arquivos de texto simples para armazenar na tabela teradata após as transformações da Informatica. O arquivo contém 14 campos (separados por ~). Mas como os registros estão sendo espalhados em várias linhas, a informatica não é capaz de captá-lo.
Existe alguma maneira de juntarmos o registro contando o delimitador usando sed / awk ou qualquer outro comando?
Registro de amostra ---
48602040112~4100010080701242015~2010-01-21 10:23:44~Foods~7~Poultry ~Perdue Smart Chicken~Circular~06
-JAN-10~24-JAN-10~$5.99~24 oz., select varieties
up to 4 at this price, additional
Save up to $4.00
load up on savings~~1598
Idealmente, deve ser como -
48602040112~4100010080701242015~2010-01-21 10:23:44~Foods~7~Poultry ~ Perdue Smart Chicken~Circular~06-JAN-10~24-JAN-10~$5.99~24 oz., select varieties up to 4 at this price, additional Save up to $4.00 load up on savings~~1598
Se não for óbvio, contém novos caracteres de linha.
tr -d \n <infile | tr \~ \n | paste -d~ - - - - - - - - - - - - - -
Isso vai funcionar.
Você pode tentar usar sed
:
sed -rn ':a;/^([^~]*~){13}[^~]*$/!{N;s/\n//;ba};p' yourfile.tsv
O que faz
O script tem três partes separadas por um ;
:
:a
define um rótulo que podemos ramificar para /^([^~]*~){13}[^~]*$/!{N;s/\n//;ba}
procura por uma coluna completa
/^([^~]*~){13}[^~]*$/
procura por uma linha com exatamente 14 campos (0 ou mais ocorrências de qualquer coisa que não seja ~
), separadas por 13 ocorrências de ~
. !
Inverte o resultado da pesquisa (se não for encontrado, então ...) {N;s/\n//;ba}
do bloco que é executado se a coluna não estiver completa
N
lê em outra linha s/\n//
remove a nova linha entre as duas linhas ba
ramificações (b) para o nosso rótulo previamente definido (a) p
imprime a coluna completa Não está claro como decidir se deseja ingressar em um campo dividido com um espaço ou sem espaço. 06<NL>-JAN-10
precisa ter a nova linha removida, enquanto varieties<NL>up to
precisa substituí-la por um espaço.
Ignorando a preocupação acima, podemos chegar a este protótipo do comando Awk:
$ awk 'BEGIN { RS = "~" }
{ gsub(/\n/,"",$0);
printf("%s", $0);
if (++i < 14) { printf("~"); }
else { i = 0; printf("\n"); } }' < in.txt > out.txt
Recebemos o awk para dividir os registros em ~
para que cada campo seja realmente um registro. Em seguida, apenas apare os espaços em branco de cada registro com gsub
e imprima-o seguido pelo separador, se for o campo 1 a 13, ou então seguido por uma nova linha, se for 14 (e redefina a contagem).
Se o número de campos não for divisível por 14, você receberá uma última linha incompleta na saída, terminada por ~
em vez de nova linha.
Uma maneira possível de lidar com o problema da junção é deixar as novas linhas no lugar ou, possivelmente, substituí-las por algum caracter que não ocorra nos dados. Faça a junção como uma etapa de pós-processamento. Suponha que @
não ocorra nos dados. Se substituirmos as novas linhas por @
, poderemos aplicar algumas substituições de padrão simples com as ferramentas usuais de processamento de texto. Por exemplo, a substituição ao longo das linhas de s/([0-9])@-/-/
manipula datas quebradas como 06@-JAN
.
Pode ser necessário que essa lógica entenda o tipo de dados do campo específico que requer remoção de nova linha, para que ele possa, por exemplo, tratar datas especialmente.
Tags files text-processing awk sed