바이트와 글자는 달라
파일에는 바이트가 있고 도구는 그 바이트가 어떤 문자 인코딩을 따른다고 가정해. UTF-8, UTF-16, ISO-8859-1은 같은 바이트를 서로 다르게 해석하므로 가정이 틀리면 글자가 깨지거나 변환 명령이 실패해.
인코딩 확인하기
file --mime-encoding file.txt
iconv -f UTF-8 -t UTF-8 file.txt >/dev/nullfile의 결과는 추정일 수 있어. 두 번째 명령이 실패하면 적어도 입력 전체가 유효한 UTF-8은 아니라는 증거가 돼.
명시적으로 변환하기
iconv -f ISO-8859-1 -t UTF-8 in.txt > out.txt
iconv -f UTF-16 -t UTF-8 win.txt > mac.txt-f는 원본 인코딩이고 -t는 결과 인코딩이야. 원본을 잘못 지정하면 명령이 성공해도 의미가 손상될 수 있어.
BOM이라는 보이지 않는 머리말
UTF-8 BOM은 파일 앞의 EF BB BF 세 바이트야. GNU sed에서는 sed -i '1s/^\xef\xbb\xbf//' file, Perl에서는 perl -i -pe 's/^\x{FEFF}//' file로 제거할 수 있어. 먼저 실제 바이트를 확인하고 원본을 보존해. 파일을 직접 바꾸는 옵션은 구현별 차이가 있으니 표본에서 검증해야 해.
줄바꿈 형식
- Unix의 LF는
\n하나를 사용해. - Windows의 CRLF는
\r\n을 사용해. - 옛 Mac의 CR은
\r하나를 사용했어.
tr -d '\r' < in.txt > out.txt
file out.txt
LC_ALL=C grep -n $'\r' out.txt마지막 grep이 아무 줄도 출력하지 않는지 확인해. 원본을 바로 덮어쓰지 않으면 diff와 표본 확인 뒤에 결과를 반영할 수 있어.
정규식 결과가 달라지는 이유
$는 줄 끝을 기준으로 매치하지만 CRLF 파일에서는 줄 끝 앞에 \r가 남을 수 있어. 개발 머신에서는 통과한 처리가 Windows를 거친 파일에서 실패하는 흔한 원인이야.
인코딩 판정에는 여러 증거가 필요해
ASCII만 든 텍스트는 여러 인코딩에서 동시에 유효해. 메타데이터, BOM, 실제 바이트, 파일을 만든 프로그램의 문서를 함께 보고 판정해. 감지 명령 하나를 확정적 사실처럼 믿지 마.
변환은 읽기와 쓰기의 두 단계야
iconv -f A -t B는 먼저 A로 해석하고 B로 다시 써. 대표 표본의 의미와 왕복 결과를 확인하고 원본 체크섬을 남겨. 그래야 잘못된 원본 인코딩을 지정했을 때 되돌릴 수 있어.