일단 "man bash"에서 read 명령에 대한 도움말을 보시면 아실 수 있듯 "-n" 옵션을 통해 읽어들이는 글자의 최대 개수를 지정할 수 있습니다. 그렇다면 이렇게 시도해 볼 수 있겠군요.
while read -n 256 chars; do echo "${chars}"; sleep 0.1; done < filename
근데 이렇게 하면 256글자가 넘는 행이 줄줄이 쪼개지는 문제가 발생합니다. 한편으로, 256글자 이하의 행은 한 줄씩 읽어들이면서 sleep을 합니다. (수십만 행의 로그 파일에서는 대략 무시무시한 일이죠.) 이건 결국 read가 개행문자를 만나면 읽기를 중단하는 문제 때문입니다.
그렇다면 이렇게 시도해 볼 수도 있습니다. 일단 delimiter라는 파일을 만들어서 다음과 같은 문자를 하나 덜렁 집어넣습니다.
%
단, 이 문자는 압축하려고 하시는 로그 파일에 내에는 존재하지 않는 문자여야 합니다. grep으로 찾아보시... 이런, 그러면 CPU 사용량이 올라가면서 경보가 울리겠군요 :-)
뭐, 여튼 집어넣은 다음에;; 다음과 같은 식으로 명령을 내려주시면 됩니다.
cat some.log delimiter | while read -d "%" -n 25600 chars; do echo -n "${chars}"; sleep 0.1; done
하지만 이렇게 해도 역시 개행문자 때문에 가끔씩 2개의 줄이 하나로 이어져서 출력되는 문제가 발생합니다. 뭔가... 개행문자에 대한 '특단의 조처'가 필요한 상황입니다.
개행문자까지도 아예 인코딩을 해버려서 read 명령이 손대지 못하도록 해버리면 어떨까요? 그래서 이메일이나 암호화 프로그램 등에서 종종 쓴다는 base64 인코딩을 이용해 봤습니다. 압축을 하는 명령까지 함께 추가했습니다.
http://kldp.org/node/81492
http://kldp.org/node/81492 에서 이어지는 질문이로군요 :-)
일단 "man bash"에서 read 명령에 대한 도움말을 보시면 아실 수 있듯 "-n" 옵션을 통해 읽어들이는 글자의 최대 개수를 지정할 수 있습니다. 그렇다면 이렇게 시도해 볼 수 있겠군요.
근데 이렇게 하면 256글자가 넘는 행이 줄줄이 쪼개지는 문제가 발생합니다. 한편으로, 256글자 이하의 행은 한 줄씩 읽어들이면서 sleep을 합니다. (수십만 행의 로그 파일에서는 대략 무시무시한 일이죠.) 이건 결국 read가 개행문자를 만나면 읽기를 중단하는 문제 때문입니다.
그렇다면 이렇게 시도해 볼 수도 있습니다. 일단 delimiter라는 파일을 만들어서 다음과 같은 문자를 하나 덜렁 집어넣습니다.
단, 이 문자는 압축하려고 하시는 로그 파일에 내에는 존재하지 않는 문자여야 합니다. grep으로 찾아보시... 이런, 그러면 CPU 사용량이 올라가면서 경보가 울리겠군요 :-)
뭐, 여튼 집어넣은 다음에;; 다음과 같은 식으로 명령을 내려주시면 됩니다.
하지만 이렇게 해도 역시 개행문자 때문에 가끔씩 2개의 줄이 하나로 이어져서 출력되는 문제가 발생합니다. 뭔가... 개행문자에 대한 '특단의 조처'가 필요한 상황입니다.
개행문자까지도 아예 인코딩을 해버려서 read 명령이 손대지 못하도록 해버리면 어떨까요? 그래서 이메일이나 암호화 프로그램 등에서 종종 쓴다는 base64 인코딩을 이용해 봤습니다. 압축을 하는 명령까지 함께 추가했습니다.
(헥헥~) 이렇게 하니 제 PC에서 30%가 좀 넘는 CPU 사용량을 보이면서 40MB로 로그 파일을 압축하는데 6분이 걸리더군요...
근데 파이프를 줄줄이 이어붙여서인지 bash 프로세스가 CPU 사용량의 대부분을 차지합니다. 한편으로 -n 옵션의 값을 크게 하면 처리 속도는 빨라지지만 bash의 CPU 사용량이 팍팍 증가합니다. 또한 sleep 시간을 줄여도 bash의 CPU 사용량이 증가합니다.
bash 프로세스가 대부분의 CPU 시간을 차지하는 건 배보다 배꼽이 큰 상황이죠:-) 그리하여... 원래 글에서 익명사용자님께서 작성해 주신 프로그램을 이용하는 것을 추천합니다.
& 덕분에 재밌게 놀아봤습니다.
&& 정작 딱 떨어지는 솔루션은 제공해 드리지 못했군요:-) 그건 이후 나타나실 어느 쉘스크립트 구루님께서...;;
----
$PWD `date`
$PWD `date`
답변 감사드립니다.
답변 감사드립니다. 저도 -n 옵션을 써 봤으나.. 한 줄씩 읽는 원칙은 변하지 않더군요..
두 분다 치환을 전제로 솔루션을 제공해 주셨군요.
본래 간단히 하려고 bash shell 로 하는 방법을 물어봤으나..
아무래로 전에 익명 사용자님이 작성해 주신 방법대로
c 코드를 이용하는 편이 나을 것 같아요.
애써 주신거 너무 너무 감사합니다.
짜깁기. IFS=cat "$1" |
짜깁기.
테스트를 C 소스로 하다보니 tab 문자가 걸려서 IFS 를 없애버렸습니다.
때문에... 스크립트 파일 형태로 밖에 못 쓰겠군요.
역시 C 소스로 테스트 하다보니
\
가 걸려서 read 옵션에 -r 추가.\n 을 ESC 로 바꿔치기...
간단히 하려고 tr 을 사용했는데 perl 이나 sed 사용하면 완벽한 ESC sequence 를 만들어서 치환할 수 있을 것으로 예상됩니다.
예를 들어
뭐 이렇게...
어쨌든 지금은 ESC 하나만 사용하므로 원본 문서가 ESC sequence 로 예쁘게 꾸며진 문서라면 g.g.
보시다시피 블록사이즈는 16자로 했는데,
버그가 있습니다.
맨 마지막블록을 항상 잃어버리는군요.
버그 사냥은 ... 직접 해보심이...
kldp 가 code complete 을 해주는 곳이 아니잖아요 ?
newline 상관없이
newline 상관없이 일정한 바이트만큼 읽어오려면 이런 방법도 있습니다.
첫번째 라인 만큼은 한 라인 전체를 읽어오게 됩니다만..
--
War doesnt determine whos right, just whos left.
War doesnt determine whos right, just whos left.
환상적이군요!ㅋ 근데
환상적이군요!ㅋ
근데 중간에 date는 별 의미없이 찍는거죠?
흠.. 그리고 perl 구분에는 sleep 말고 usleep 은 없나요?
1초는 너무 길어요 =_=
인용: 첫번째 라인
BEGIN 블럭을 써도 안될까요?
$ cat test2.txt | while
$Myoungjin_JEON=@@=qw^rekcaH lreP rehtonA tsuJ^;$|++;{$i=$like=pop@@;unshift@@,$i;$~=18-length$i;print"\r[","~"x abs,(scalar reverse$i),"~"x($~-abs),"]"and select$good,$day,$mate,1/$~for 0..$~,-$~+1..-1;redo}
감사합니다. 근데,
감사합니다.
근데, newline이 모조리 사라지네요..
$ cat test2.txt | while
$ cat test2.txt | while x=`dd ibs=10 count=1 2>/dev/null` && test x"$x" != x ;do echo "$x"; sleep 1; done
echo에서 따옴표가 빠졌군요.
$Myoungjin_JEON=@@=qw^rekcaH lreP rehtonA tsuJ^;$|++;{$i=$like=pop@@;unshift@@,$i;$~=18-length$i;print"\r[","~"x abs,(scalar reverse$i),"~"x($~-abs),"]"and select$good,$day,$mate,1/$~for 0..$~,-$~+1..-1;redo}
헛, echo 에 따옴표
헛, echo 에 따옴표 차이가 이런 것이였군요~
근데 이번엔 10byte 마다 newline 이 생기네요..
echo -n "$x"
echo -n "$x"
$Myoungjin_JEON=@@=qw^rekcaH lreP rehtonA tsuJ^;$|++;{$i=$like=pop@@;unshift@@,$i;$~=18-length$i;print"\r[","~"x abs,(scalar reverse$i),"~"x($~-abs),"]"and select$good,$day,$mate,1/$~for 0..$~,-$~+1..-1;redo}
echo -n "$x" 이제 된 것
echo -n "$x"
이제 된 것 같군요.
쓰레드 닫았으면 좋겠습니다.
$Myoungjin_JEON=@@=qw^rekcaH lreP rehtonA tsuJ^;$|++;{$i=$like=pop@@;unshift@@,$i;$~=18-length$i;print"\r[","~"x abs,(scalar reverse$i),"~"x($~-abs),"]"and select$good,$day,$mate,1/$~for 0..$~,-$~+1..-1;redo}
캄사합니다 ㅠ_ㅠ
문제가 완벽하게 해결이 되었네요.
이번, 저번 쓰레드를 통해서 shell script와 많이 친해졌습니다.
하하.
다시한번 감사드립니다.
.
.
댓글 달기