Manipular arquivo texto e para gerar comandos sed.
Olá pessoal, alguém consegue ajudar?
Tenho um arquivo texto com o seguinte conteúdo (formado com 3 colunas): 1ª coluna é um caminho para um arquivo, a 2ª coluna é o nº da linha dentro do arquivo e a 3ª o conteúdo da linha.
Se o nome do arquivo se repetir, ou seja, se ele tiver mais de uma ocorrência, está em sequência e o número da linha sempre da menor para a maior.
Exemplo:
/tmp/teste1/arq1.conf:99:string 3
/tmp/teste2/arq1.conf:103:string 1
/tmp/teste2/arq1.conf:122:string qualquer
/tmp/teste2/arq1.conf:115:abracadabra teste
/tmp/teste3/arq1.conf:106:abcde
/tmp/teste3/arq1.conf:155:ola mundo
/tmp/teste4/arq1.conf:60:string qualquer 2
/tmp/teste5/arq1.conf:10:ola mundo
Reparem que podem ter mais de uma linha para o mesmo arquivo e este arquivo é gerado dinamicamente.
A partir dele, preciso gerar uma saída contendo comandos sed de alteração em cada arquivo desta lista da seguinte forma:
Se o nome do arquivo tiver somente uma ocorrência (ex. /tmp/teste1/arq1.conf, /tmp/teste4/arq1.conf e /tmp/teste5/arq1.conf) ou várias ocorrências mas sendo a última, gerar o sed para substituir o conteúdo da linha por uma string pré-definida.
Se o arquivo tiver mais ocorrência mas NÃO é a última na sequência, gerar o sed para remover a linha e este comando deve estar depois dos comandos de substituição.
Digamos que se a string de substituição for xpto, a saída deveria ser igual a:
sed -i "99s/.*/xpto/g" /tmp/teste1/arq1.conf
sed -i "115s/.*/xpto/g" /tmp/teste2/arq1.conf
sed -i "103d" /tmp/teste2/arq1.conf
sed -i "122d" /tmp/teste2/arq1.conf
sed -i "155s/.*/xpto/g" /tmp/teste3/arq1.conf
sed -i "106d" /tmp/teste3/arq1.conf
sed -i "60s/.*/xpto/g" /tmp/teste4/arq1.conf
sed -i "10s/.*/xpto/g" /tmp/teste5/arq1.conf
De preferência, se for através de awk (ou sed se possível) seria melhor ainda porque não queria loops for / while.
Tenho um arquivo texto com o seguinte conteúdo (formado com 3 colunas): 1ª coluna é um caminho para um arquivo, a 2ª coluna é o nº da linha dentro do arquivo e a 3ª o conteúdo da linha.
Se o nome do arquivo se repetir, ou seja, se ele tiver mais de uma ocorrência, está em sequência e o número da linha sempre da menor para a maior.
Exemplo:
/tmp/teste1/arq1.conf:99:string 3
/tmp/teste2/arq1.conf:103:string 1
/tmp/teste2/arq1.conf:122:string qualquer
/tmp/teste2/arq1.conf:115:abracadabra teste
/tmp/teste3/arq1.conf:106:abcde
/tmp/teste3/arq1.conf:155:ola mundo
/tmp/teste4/arq1.conf:60:string qualquer 2
/tmp/teste5/arq1.conf:10:ola mundo
Reparem que podem ter mais de uma linha para o mesmo arquivo e este arquivo é gerado dinamicamente.
A partir dele, preciso gerar uma saída contendo comandos sed de alteração em cada arquivo desta lista da seguinte forma:
Se o nome do arquivo tiver somente uma ocorrência (ex. /tmp/teste1/arq1.conf, /tmp/teste4/arq1.conf e /tmp/teste5/arq1.conf) ou várias ocorrências mas sendo a última, gerar o sed para substituir o conteúdo da linha por uma string pré-definida.
Se o arquivo tiver mais ocorrência mas NÃO é a última na sequência, gerar o sed para remover a linha e este comando deve estar depois dos comandos de substituição.
Digamos que se a string de substituição for xpto, a saída deveria ser igual a:
sed -i "99s/.*/xpto/g" /tmp/teste1/arq1.conf
sed -i "115s/.*/xpto/g" /tmp/teste2/arq1.conf
sed -i "103d" /tmp/teste2/arq1.conf
sed -i "122d" /tmp/teste2/arq1.conf
sed -i "155s/.*/xpto/g" /tmp/teste3/arq1.conf
sed -i "106d" /tmp/teste3/arq1.conf
sed -i "60s/.*/xpto/g" /tmp/teste4/arq1.conf
sed -i "10s/.*/xpto/g" /tmp/teste5/arq1.conf
De preferência, se for através de awk (ou sed se possível) seria melhor ainda porque não queria loops for / while.
Luiz Gustavo
Curtidas 0
Respostas
Arthur Heinrich
11/03/2023
Você pode acessar o arquivo com o comando "tac", que lê o arquivo do fim para o começo. Assim, se o arquivo lido for diferente do anterior, monta a linha do update. Se for igual, monta o delete.
GOSTEI 0
Luiz Gustavo
11/03/2023
Oi Arthur, obrigado pela sugestão, mas no caso de ter 3 iguais, ele fará o delete deles e o último dele (no caso do primeiro por causa do tac) precisa ser update.
GOSTEI 0
Arthur Heinrich
11/03/2023
Oi Arthur, obrigado pela sugestão, mas no caso de ter 3 iguais, ele fará o delete deles e o último dele (no caso do primeiro por causa do tac) precisa ser update.
Exatamente. Foi o que eu disse.
Você faz um loop invertido e compara o nome do arquivo de cada linha, com o nome do arquivo da linha anterior. Se for diferente, monta o update. Se for igual, monta o delete
LINHA ARQ. ANT. COMANDO ------------------------------------------- --------------------- ------- /tmp/teste5/arq1.conf:10:ola mundo update /tmp/teste4/arq1.conf:60:string qualquer 2 /tmp/teste5/arq1.conf update /tmp/teste3/arq1.conf:155:ola mundo /tmp/teste4/arq1.conf update /tmp/teste3/arq1.conf:106:abcde /tmp/teste3/arq1.conf delete /tmp/teste2/arq1.conf:115:abracadabra teste /tmp/teste3/arq1.conf update /tmp/teste2/arq1.conf:122:string qualquer /tmp/teste2/arq1.conf delete /tmp/teste2/arq1.conf:103:string 1 /tmp/teste2/arq1.conf delete /tmp/teste1/arq1.conf:99:string 3 /tmp/teste2/arq1.conf update
GOSTEI 0
Arthur Heinrich
11/03/2023
Eu inverti as linhas errado no exemplo anterior, mas a lógica está correta:
LINHA ARQ. ANT. COMANDO ------------------------------------------- --------------------- ------- /tmp/teste5/arq1.conf:10:ola mundo update /tmp/teste4/arq1.conf:60:string qualquer 2 /tmp/teste5/arq1.conf update /tmp/teste3/arq1.conf:155:ola mundo /tmp/teste4/arq1.conf update /tmp/teste3/arq1.conf:106:abcde /tmp/teste3/arq1.conf delete /tmp/teste2/arq1.conf:122:string qualquer /tmp/teste3/arq1.conf update /tmp/teste2/arq1.conf:115:abracadabra teste /tmp/teste2/arq1.conf delete /tmp/teste2/arq1.conf:103:string 1 /tmp/teste2/arq1.conf delete /tmp/teste1/arq1.conf:99:string 3 /tmp/teste2/arq1.conf update
GOSTEI 0
Luiz Gustavo
11/03/2023
Obrigado Arthur, pelas idéias. Consegui fazer com awk usando array.
GOSTEI 0