a saída awk tem retornos de linha extras e é armazenada em buffer

1

Meu objetivo final é fazer com que uma caixa de diálogo de andamento do zenity funcione durante a codificação com o fdkaac.

Eu comecei com algum código que está trabalhando quando eu codifico "aa.wav" para "aa.mp3" com lame. Isso resulta em uma barra de progresso que é atualizada de 0 a 100%:

lame -m auto -V 4 aa.wav aa.mp3 | awk -vRS='\r' '(NR>3){gsub(/[()%|]/," ");print $2; fflush();}' | zenity --progress --title="Title" --text="encoding" --auto-close

Agora eu corro este código com fdkaac:

fdkaac --profile 2 --bitrate-mode 5 aa.wav -o aa.aac

Isso resulta na saída da tela no final da codificação:
[100%] 05: 31.227 / 05: 31.227 (43x), ETA 00: 00.000 | 14607096/14607096 amostras processadas em 00: 07.689

Durante a codificação, a primeira linha é impressa e o [100%] atualiza suavemente de 0 a 100 durante a codificação. No final da codificação, a segunda linha é impressa.

Com base nisso, modifico a pesquisa do gsub e substituo por: gsub (/ [[%] /, "") para selecionar os dados.

Agora executo este código:

fdkaac --profile 2 --bitrate-mode 5 aa.wav -o aa.aac 2>&1 | awk -vRS='\r' '(NR>3){gsub(/[\[%]/," ");print $1; fflush();}' | zenity --progress --title="Title" --text="Encoding" --auto-close

O resultado não é o que eu esperava. A caixa de diálogo de progresso aparece com 0% ... e depois de algum tempo pula para 50% ... e depois desaparece quando a codificação é concluída.

Então, dou uma olhada nos dados indo zenity com este código:

fdkaac --profile 2 --bitrate-mode 5 aa.wav -o aa.aac 2>&1 | awk -vRS='\r' '(NR>3){gsub(/[\[%]/," ");print $1; fflush();}' 

A saída da tela não é o que eu esperava. 1 a 50 são todas impressas ao mesmo tempo, mas em linhas consecutivas e, em seguida, 50 a 100 são impressas em linhas consecutivas quando a codificação é concluída:

1
2
3
4
5

...

48
49
50

e continua até 50. e depois a saída continua em linhas separadas de 50 a 100 (novamente impressas todas ao mesmo tempo):

50
51
52

..

98
99
100

Assim, o problema é aparente ... Os dados de saída são impressos em dois lotes (como visto na caixa de diálogo). E os dados estão aparecendo em linhas consecutivas. (A saída lame após o filtro awk é toda impressa na mesma linha e atualizada sem problemas).

Eu suspeito que o problema tenha a ver com retornos extras de carro, mas eu não sei como me livrar deles. Eu tentei remover o comando -vRS = '\ r .. mas isso não resultou em nenhuma saída.

Eu não entendo a subsituição: RS = '\ r'. Onde a variável RS está aparecendo?

Também é estranho para mim que os dados sejam impressos exatamente em 50% e 100%. Por que não 38% ou 67%? .. então os dados estão me dizendo algo, mas não tenho certeza do que é.

    
por daniel 13.10.2015 / 04:58

2 respostas

0

O problema pode ser que fdkaac esteja armazenando em buffer sua saída quando estiver em um pipe. Tente prefixar o comando:

stdbuf -o 0 -e 0 fdkaac ... 2>&1 | ...

onde -o é para stdout e -e para stderr.

Se você quiser tentar uma alternativa ao awk, você pode usar um script de shell. Verifique se o seu shell é bash então

stdbuf -o 0 -e 0 fdkaac ... 2>&1 | 
(IFS="$IFS%[]"
while read -d$'\r' junk1 percent junk2
do  echo "$percent"
done) |
zenity --progress --title="Title" --text="encoding" --auto-close

Ao definir o IFS (bash field separator) para incluir mais 3 caracteres, "% []", eles se tornam efetivamente espaços na entrada, portanto, o read com o retorno de carro do delimitador (-d) deve colocar a primeira palavra da linha em var junk1, a segunda em porcentagem, e o resto no lixo2. Podemos então apenas ecoar a variável que deveria estar segurando apenas o número.

Nota: você precisa tentar isso sem o bit zenity para ver se você está recebendo o campo numérico. Eu não sei porque eu tive que usar um primeiro var junk1, como a porcentagem deve ser o primeiro campo na linha, mas se você não conseguir o número desejado, tente remover a variável junk1 da leitura.

    
por 13.10.2015 / 08:52
0

Vamos detalhar seu comando do awk: awk -vRS='\r' '(NR>3){gsub(/[()%|]/," ");print $1; fflush();}'

O separador de registro é \ r, o separador de campo é [\ t] +. Os caracteres ()% | será substituído por espaço. Você está tomando o primeiro campo.

Baseado neste formato: [100%] 05:31.227/05:31.227 (43x), ETA 00:00.000 O seguinte será passado para o zenity: [100]

Talvez seu awk seja algo mais parecido com: awk -vRS='\r' '(NR>3){gsub(/[()%|[]]/," ");print $1; fflush();}'

Ou, melhor ainda, remova o argumento posicional: gawk -vRS='\r' 'match($0, /([0-9]+)%/, ary) {print ary[1]}'

    
por 13.10.2015 / 05:21