awk 출력에는 추가 캐리지 리턴이 있으며 버퍼링됩니다.

awk 출력에는 추가 캐리지 리턴이 있으며 버퍼링됩니다.

나의 궁극적인 목표는 fdkaac로 코딩할 때 zenity 진행 대화 상자를 얻는 것입니다.

처음에는 Lame을 사용하여 "aa.wav"를 "aa.mp3"로 인코딩할 때 제대로 작동하는 일부 코드로 시작했습니다. 그러면 진행률 표시줄이 0에서 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

이제 fdkaac을 사용하여 이 코드를 실행합니다.

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

그러면 인코딩이 끝나면 화면이 출력됩니다.
[100%] 05:31.227/05:31.227 (43x), ETA 00:00.000
14607096/14607096 샘플이 00:07.689에서 처리됨

인코딩하는 동안 첫 번째 줄이 인쇄되고 [100%]는 인코딩하는 동안 0에서 100까지 원활하게 업데이트됩니다. 인코딩 끝 부분에 두 번째 줄을 인쇄합니다.

이를 바탕으로 gsub 검색을 수정하고 gsub(/[[%]/," ")로 대체하여 데이터를 선택했습니다.

이제 다음 코드를 실행합니다.

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

결과는 내가 기대했던 것과 달랐습니다. 진행률 대화 상자에 0%가 표시되고... 일정 시간이 지나면 50%로 점프한 다음 인코딩이 완료되면 사라집니다.

그래서 다음 코드를 사용하여 zenity로 들어오는 데이터를 살펴보았습니다.

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

화면 출력이 예상했던 것과 다릅니다. 1부터 50까지가 동시에 모두 인쇄되지만 연속된 줄에 인쇄되고 인코딩이 완료되면 50부터 100까지 연속된 줄에 별도로 인쇄됩니다.

1
2
3
4
5

...

48
49
50

그리고 50까지 계속됩니다. 그런 다음 출력은 별도의 줄에 50에서 100까지 계속됩니다(다시 동시에 인쇄됨).

50
51
52

..

98
99
100

따라서 문제는 분명합니다. 출력 데이터는 두 개의 배치로 인쇄됩니다(대화 상자에 표시됨). 그리고 데이터는 연속된 행에 나타납니다. (awk 필터 이후의 잘못된 출력은 모두 같은 줄에 인쇄되고 원활하게 업데이트됩니다.)

문제가 추가 캐리지 리턴과 관련된 것으로 의심되지만 이를 제거하는 방법을 모르겠습니다. -vRS='\r 명령을 제거하려고 시도했지만 전혀 출력이 제공되지 않았습니다.

대체를 이해할 수 없습니다: RS='\r'. 변수 RS는 어디에 나타납니까?

데이터를 출력해 보면 정확히 50%와 100%인 것도 놀랍습니다. 왜 38%나 67%가 아닌가? ..데이터가 나에게 뭔가를 말해주긴 하지만 그게 무엇인지는 잘 모르겠습니다.

답변1

문제는 fdkaac출력이 파이프로 이동하면서 출력을 버퍼링하는 것일 수 있습니다. 명령 앞에 다음을 붙여보세요.

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

그 중 -o는 stdout을 나타내고 -e는 stderr을 나타냅니다.


awk의 대안을 시도하려면 쉘 스크립트를 사용할 수 있습니다. 쉘이 bash인지 확인하십시오

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

추가 3개 문자 "%[]"를 포함하도록 IFS(bash 필드 구분 기호)를 설정하면 실제로 입력에서 공백처럼 됩니다. 따라서 read구분 기호 캐리지 리턴(-d)을 사용하면 줄이 다음과 같아야 합니다. 한 단어가 var에 입력됩니다. 쓰레기 1, 백분율 두 번째, 나머지 쓰레기 2. 그런 다음 숫자만 보유해야 하는 변수를 에코할 수 있습니다.

참고: 숫자 필드를 얻을 수 있는지 확인하려면 zenity 비트 없이 이 작업을 시도해야 합니다. 백분율이 행의 첫 번째 필드여야 하기 때문에 첫 번째 varjunk1을 사용해야 하는 이유를 모르겠습니다. 그러나 원하는 숫자를 얻지 못한 경우 읽기에서junk1 변수를 제거해 보십시오.

답변2

awk 명령을 분석해 보겠습니다. awk -vRS='\r' '(NR>3){gsub(/[()%|]/," ");print $1; fflush();}'

레코드 구분 기호는 \r이고 필드 구분 기호는 [\t]+입니다. ()%| 문자는 공백으로 대체됩니다. 첫 번째 필드를 차지하고 있습니다.

이 형식을 기반으로 [100%] 05:31.227/05:31.227 (43x), ETA 00:00.000 다음이 zenity에 전달됩니다.[100]

아마도 당신의 awk는 다음과 같아야 할 것입니다: awk -vRS='\r' '(NR>3){gsub(/[()%|[]]/," ");print $1; fflush();}'

아니면 위치 매개변수를 제거하는 것이 더 좋습니다.gawk -vRS='\r' 'match($0, /([0-9]+)%/, ary) {print ary[1]}'

관련 정보