Eu tenho um arquivo enorme para analisar e preciso pesquisar e substituir texto, mas em campos específicos, compartilhando uma pequena amostra para referência chamada dest. a primeira linha é o cabeçalho para referência.
cat dest
ID|NAME|COMPANY|NUMBER
1001|Adam||15001
1002|eve|adam&eve|15002
1003|||
1004|||50000
1005|||50001
Eu tenho arquivos separados que contêm padrão para corresponder, texto a ser substituído e texto a ser substituído
cat src
1003||15003
1004|50000|15004
1005|50001|15005
para que eu possa executar um loop while abaixo com sed para alcançar as últimas 2 linhas do arquivo src.
cat src | while IFS=$'|'; read id old new; do sed -i "/^${id}/s/${old}/${new}/" dest; done
mas para ID=1003
recebo uma string vazia para $old
, e ele substituirá todas as colunas vazias no arquivo dest para esse ID. O que eu quero evitar. O que eu quero fazer é substituir apenas o último campo.
DESEJADO:
ID|NAME|COMPANY|NUMBER
1001|Adam||15001
1002|eve|adam&eve|15002
1003|||15003
1004|||15004
1005|||15005
Eu poderia usar o awk, pois é mais granular, quando se trata de dados colunares. mas o awk imprimirá várias vezes para stdout, tanto quanto eu entendo, o que também não é prático no meu caso.
então existe uma maneira de fazer isso de maneira inteligente e concisa?
FS: S eperador de campo
OFS: S eperador de campo de saída
NR==FNR: Um idioma de condição sempre verdadeiro para o primeiro arquivo de entrada.
NR está presente o número total de registros que awk leu ;
FNR está presente no número de registros de cada arquivo individual.
id[$1, $2]=$3
: uma matriz awk associada.Nome:
chave id: coluna#1+coluna#2
valor: coluna#3
primeiro bloco é executado apenas para o primeiro arquivo de entrada, i. e, arquivo src .
Neste
$4=($1, $4) in id? id[$1, $4]: $4
, estamos atualizando o valor da última coluna ($NF
ou$4
) do segundo arquivo, i. e, arquivo dest da combinação de chaves correspondentes da coluna#1+coluna#4 na matriz id , se encontrado, retorne esse valor (id[$1, $4]
), caso contrário, copie seu valor atual.Outra
awk
solução, que pressupõe que as linhas desrc
serão usadas exatamente uma vez cada e em ordem. Isso nos permite acompanhar apenas a próxima linhasrc
até que ela tenha sido usada e, em seguida, ler a próxima.Se o sinalizador
have
não estiver definido ou for zero, a próxima linha desrc
será lidaline
e dividida no arraypat
. Isso é feito no! have
bloco.Se a linha atual de entrada de
dest
tiver um 1º campo idêntico ao primeiro elemento depat
, testaremos o 4º campopat[2]
e o substituiremospat[3]
se forem iguais. Ohave
sinalizador é então redefinido para zero para acionar a leitura de uma nova linha desrc
.A trilha
1
no final doawk
programa faz com que o registro (possivelmente modificado) seja gerado.A saída, dados os dados na pergunta: