brunch

You can make anything
by writing

C.S.Lewis

by 이권수 Mar 03. 2024

[코딩 챌린지] #1. 나만의 wc 만들기

파일 라인 수, 바이트 수 등을 체크하는 wc command 만들어보기

코딩 챌린지 참여하기!


wc 설명

wc 명령어는 Linux나 Unix 시스템에서 텍스트 파일의 줄(line), 단어(word), 바이트(byte) 또는 문자(character) 수를 세는 데 사용된다. 이 명령어의 이름은 "word count"의 약자이다. wc는 특히 파일의 내용을 분석하거나 텍스트 데이터의 양을 측정할 때 유용하다.


실제 개발자로 일하거나 DevOps 엔지니어로 일하게 되면, wc를 마주하게 되는 경우가 종종 있다. 예컨대, 파일을 다운로드하거나, 데이터를 크롤링했는데, 라인수가 얼마나 되는지를 보고 싶을 때 wc를 사용한다. 필자의 경우 주로 csv와 같이 대용량 데이터를 쉘에서 열기 전에 전체 라인수 등을 파악할 때 종종 사용한다.


기본적인 wc 명령어의 구조는 다음과 같다.


wc [옵션] [파일명] 

이 명령어를 파일명 없이 실행하면, 표준 입력에서 읽어 들인 데이터에 대해 통계를 출력한다. 사용자가 입력을 종료하려면 ctrl + D를 누르면 된다.


대표적인 wc 옵션은 다음과 같다.  

-l 또는 --lines: 줄 수만 세서 출력한다.

-w 또는 --words: 단어 수만 세서 출력한다.

-c 또는 --bytes: 바이트 수만 세서 출력한다. 이 옵션은 파일의 크기를 바이트 단위로 알고 싶을 때 유용하다.

-m 또는 --chars: 문자 수만 세서 출력한다. 다국어 처리나 멀티바이트 문자셋을 사용할 때 유용할 수 있다.


나만의 wc 도구 만들기

먼저 wc 도구를 만들기 위해서 옵션을 받아야 한다. 대표적으로 구현할 옵션은 앞서 설명한 -l, -w, -c, -m 이므로 4가지 옵션을 받을 수 있다.


python에서 argument를 사용하고 싶다면, argparse 패키지를 사용하면 된다. python을 활용하여 만든 도구에서 커멘드라인으로 들어와야 하는 argument를 사용할 때, 대부분 argparse 패키지를 사용한다. argparse로 argument를 추가할 때는 어떤 이름으로 데이터를 받을지 넣어야 한다.


wc에서는 -l, -w, -m, -c 옵션만 받고 그 뒤에 값을 받지 않기 때문에, action은 store_true를 사용했다. 이 의미는 해당 flag가 주어지면, 변수의 값을 True로 세팅해 준다는 의미이다.


여기서 한 가지 주의해야 할 점은 맨 마지막에 파일 이름은 positional argument로 받아야 한다는 점이다. 다시 말해, --file test.txt 가 아니라 그냥 test.txt를 바로 넘겨주어야 한다. 만약 파일 이름을 전달하지 않으면 stdin(standard input)을 통해서 데이터가 들어온다고 간주한다.


그다음은 아무런 옵션을 주지 않는 경우나 여러 옵션을 동시에 주는 경우를 다루기 위해 실제 전달된 옵션을 확인하는 부분을 추가했다. store_true로 전달받은 argument 중에서 실제로 true로 설정된 경우만 골라낸다. 만약 아무런 인자도 받지 못했다면, default로 -c, -w, -l 옵션을 추가한다.



이후에는 파일을 읽으면서 라인 수, 글자 수, 그리고 단어 수를 추가한다. 실제 파일 이름을 전달받은 경우에는 open() 함수를 사용하여 파일을 읽는다. stdin으로 들어오는 데이터의 경우 바로 buffer에서 읽을 수 있기 때문에, 별도로 file open을 하지 않아도 된다.


여기서 유의할 점이 하나 있다. wc는 줄 바꿈을 시행할 때, 개행문자(\n) 뿐만 아니라, 캐리지 리턴(\r, Carriage Return, CR)을 계산한다. 그런데, file을 읽어 들일 때는 캐리지 리턴이 들어오지 않는다. 따라서 만약 line을 그대로 읽어서 계산하게 되면, stdin으로 들어왔을 때랑 file을 읽었을 때랑 데이터가 달라진다. 따라서, 캐리지 리턴을 추가하기 위해 \n을 모두 \r\n으로 변경했다. 


참고로, open() 함수의 파라미터 중에 newline이라는 파라미터를 통해 개행문자를 지정할 수 있다. 만약 newline 값을 지정하지 않으면, \n, \r, \r\n 모두 \n으로 인식되어 반환된다.


https://docs.python.org/3/library/functions.html#open

When reading input from the stream, if newline is `None`, universal newlines mode is enabled. Lines in the input can end in `'\n'`, `'\r'`, or `'\r\n'`, and these are translated into `'\n'` before being returned to the caller. If it is `''`, universal newlines mode is enabled, but line endings are returned to the caller untranslated. If it has any of the other legal values, input lines are only terminated by the given string, and the line ending is returned to the caller untranslated.



전체 코드는 다음과 같다.



직접 작성한 코드를 실제 wc와 비교해 보기 위해 다음의 스크립트를 수행했다.




잘못된 내용은 댓글로 남겨주시면 빠르게 정정하겠습니다. 많은 가르침 부탁드립니다.


이메일로 블로그 받아보기: https://growthminder.substack.com/subscribe

작품 선택

키워드 선택 0 / 3 0

댓글여부

afliean
브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari