Imprime o arquivo linha por linha, mas manipula o arquivo mudando a execução a meio

0

O seguinte comando bash lê o arquivo de entrada e imprime cada linha com uma pausa de 15 segundos entre eles:

IFS=$'\n';for line in $(cat file.txt | tail -n +2); do echo $line && sleep 15; done;

No entanto, como há longos atrasos entre cada linha, eu posso modificar o arquivo de entrada enquanto esse comando está sendo executado .

Por exemplo, posso modificar a quinta linha enquanto o comando só imprimiu as três primeiras linhas. 30 segundos depois, quando o comando chegar à quinta linha e imprimi-lo, eu quero mostrar a linha atualizada, em vez do arquivo, como era quando o comando foi executado pela primeira vez.


Exemplo entrada file.txt

Continentes
África
Antártida
Asia
Australia
Europa
N.America
S.America

Não há pedidos no arquivo de entrada

Entrada modificada file.txt
África
Antártida
Europa
Asia
Australia
N.America
S.America

    
por bioinform 26.10.2017 / 08:59

2 respostas

1

Você terá que ler o arquivo toda vez que for executado, tente isto:

num=1
while true; do
if [[ $num < $(wc -l file.txt) ]]; then
    awk "NR==$num" file.txt && let "num++"
else
    break
fi
sleep 15
done

Isto imprimirá uma linha, dormirá por 15 segundos e continuará, sairá quando não houver mais linhas. NR é uma variável awk incorporada de Número de registros ou número de linha.

    
por 26.10.2017 / 09:58
1

Use o seguinte e apenas acrescente ao arquivo (ou tenha muito cuidado com o modo como você o edita)

awk '{ system("echo "$0"; sleep 15") }' file.txt

O comando

O principal problema que você está tendo é como você está lendo o arquivo $(cat file.txt | tail -n +2) será executado primeiro - leia o arquivo inteiro e produza uma lista de linhas para fazer um loop antes que o loop seja iniciado. Em que ponto não importa o que acontece com o arquivo como você está feito lendo isso. Em seguida, você passa o cursor sobre essas linhas com seu comando caro.

Em vez disso, você deseja que um aplicativo leia e processe as linhas uma de cada vez. Você pode fazer isso com awk e o comando system .

awk '{ system("echo "$0"; sleep 15") }' file.txt

Aqui usamos o awk para abrir o arquivo e processá-lo linha a linha. Em cada linha, ele executará o comando "echo "$0"; sleep 15" em um shell. Note que as aspas são importantes $0 deve estar fora das aspas para sed para substituí-lo com a linha atual, caso contrário, ele é tratado como parte do comando.

Modificando o arquivo

O comando, no entanto, provavelmente não é seu único problema. Sob o capô, a maioria dos aplicativos modifica os arquivos gravando em um arquivo completamente novo e, em seguida, excluindo o antigo e renomeando o novo arquivo quando você clica em salvar. Faça isso por segurança - se eles falharem durante a gravação do arquivo, não importa, pois o arquivo original permanece intacto, somente depois de terem escrito um arquivo com sucesso, eles apagam o arquivo antigo em uma operação muito rápida, fazendo com que ele pareça arquivo foi modificado no lugar. Isso significa que o awk (ou qualquer comando que você possa usar) precisa fechar e abrir o arquivo novamente para começar a ler as modificações.

Infelizmente, a maioria dos comandos que modificam arquivos faz isso dessa maneira. Você pode, no entanto, anexar com segurança a um arquivo como

echo "Test" >> file.txt

E o comando acima irá começar a processá-lo assim que terminar todos os outros países.

Tudo isso é feito por um bom motivo e você está encobrindo uma enorme quantidade de condições de corrida e casos de canto que seriam possíveis se fosse simples fazer o que você precisa. Por um lado, o que acontece se você modificar um arquivo antes da linha que você deseja? A posição do arquivo é rastreada pela posição do byte e não pelo número da linha, portanto, se a linha que você modificar tiver um comprimento diferente, o seu aplicativo perderá onde estiver no arquivo. Além disso, você deve considerar que, mesmo que um aplicativo possa modificar um arquivo, ele está realmente gravando todo o arquivo novamente desde o início, em vez de apenas atualizar os bytes que foram alterados (novamente devido à linha que você está adicionando / movendo) tamanho para o original).

Alternativamente, você pode ler o arquivo a cada vez e acompanhar o número da linha que você é um - isso resolve alguns dos problemas acima, mas ainda há alguns casos a considerar, como o que acontece se você adicionar uma linha antes da linha que está sendo processado atualmente? Em uma solução trivial, você processará a linha atual duas vezes, o que pode ou não ser um problema. Sua melhor jogada absoluta é escrever seu próprio aplicativo para ler o arquivo, relê-lo se for modificado / excluído de você e processar as alterações no arquivo manualmente para resolver quaisquer discrepâncias, mas isso envolveria muito mais trabalho e um simples acréscimo único método como acima pode ser tudo o que é necessário para sua situação.

    
por 26.10.2017 / 10:00