format — sprintf 스타일 문자열 포매팅
format — sprintf 스타일 문자열 포매팅
숫자나 문자를 정해진 모양으로 깔끔하게 출력하고 싶을 때가 있어요. C의 sprintf처럼 변환 지정자를 써서 문자열을 만드는 Tcl 명령어가 format이에요.
본문
시그니처
format formatString ?arg arg ...?
format은 ANSI C sprintf와 비슷하게 형식화된 문자열을 만들어요. formatString이 결과를 어떻게 만들지 지정하는데, sprintf처럼 % 변환 지정자를 사용하고, 추가 인자(있다면)가 결과에 치환될 값을 제공해요. 반환값은 형식화된 문자열이에요.
동작 방식
format은 formatString을 왼쪽에서 오른쪽으로 훑어요. %가 아닌 문자는 결과 문자열에 그대로 붙고, %를 만나면 그 뒤의 문자들을 변환 지정자(conversion specifier) 로 해석해요. 변환 지정자는 그다음 차례의 arg를 특정 형식으로 변환하고, 그 결과가 지정자 자리를 대신해 결과 문자열에 들어가요. 지정자가 여럿 있으면 각각이 추가 인자 하나씩을 변환해요. 따라서 formatString에 있는 모든 지정자에 맞는 충분한 인자를 넘겨야 해요.
각 변환 지정자는 최대 여섯 부분으로 이루어져요:
- XPG3 위치 지정자 —
%뒤에 십진수와$가 오는 형태(%2$d)예요. 이 경우 변환할 값을 다음 순차 인자에서 가져오지 않고 숫자가 가리키는 인자에서 가져와요(1이 첫 번째 인자). 지정자 안에*가 있어서 여러 인자가 필요하면 그 숫자에서 시작해 연속적으로 사용해요. XPG3 위치 지정 규칙을 따르며, 한 번이라도 위치 지정자를 쓰면 모든 지정자가 위치 지정자여야 해요. - 플래그 집합 — 다음 플래그 문자들을 아무 순서로나 포함할 수 있어요.
-— 변환 결과를 필드 안에서 왼쪽 정렬(숫자는 보통 오른쪽 정렬에 앞쪽 공백).+— 양수여도 항상 부호를 붙여 출력.- 공백 — 첫 문자가 부호가 아니면 숫자 앞에 공백 하나 추가.
0— 숫자 왼쪽을 공백 대신 0으로 채움.#— 대체 출력 형태를 요청.o변환은 첫 자리가 항상 0임을 보장하고,x/X는 결과가 0이 아닐 때 앞에0x/0X를 붙여요.b는0b를 붙여요. 모든 부동소수 변환(e,E,f,g,G)에서는 결과에 항상 소수점이 있음을 보장하고,g/G에서는 끝의 0을 제거하지 않도록 지정해요.
- 필드 너비 — 십진수로 된 최소 필드 너비예요. 표 형식 출력에서 열을 맞추는 데 주로 쓰여요. 변환 결과가 최소 너비보다 짧으면 그만큼 채워요. 기본은 왼쪽에 공백을 붙이지만
0과-플래그로 0 채움·오른쪽 채움을 지정할 수 있어요.*로 지정하면 다음 인자(정수여야 함)가 최소 너비를 결정해요. - 정밀도/범위 — 온점 뒤 숫자로 된 정밀도예요. 변환 종류에 따라 의미가 달라져요.
e,E,f는 소수점 오른쪽 자릿수,g,G는 소수점 양쪽을 포함한 전체 자릿수, 정수 변환은 출력할 최소 자릿수(필요하면 앞에 0),s는 출력할 최대 문자 수(초과분은 버려짐)를 나타내요.*로 지정하면 다음 인자가 정밀도를 결정해요(숫자 문자열이어야 함). - 크기 수정자 —
ll,h,l중 하나예요.ll은 정수를 잘라내지 않고 그대로 변환하고,h는 16비트 범위로 잘라 변환하며(거의 쓸 일 없음),l은expr의wide()함수가 만드는 범위(최소 64비트)로 잘라 변환해요.h나l이 없으면expr의int()함수 범위(최소 32비트,tcl_platform배열의wordSize에 따라 결정)로 잘라요. - 변환 문자(필수) — 변환의 종류를 정하는 알파벳 문자예요.
지원되는 변환 문자:
| 문자 | 의미 |
|---|---|
d |
정수를 부호 있는 십진 문자열로 변환 |
u |
정수를 부호 없는 십진 문자열로 변환 (잘림 범위가 없으면 의미가 없어서 ll과 조합 불가) |
i |
d와 동일한 부호 있는 십진 |
o |
정수를 부호 없는 8진 문자열로 변환 |
x / X |
정수를 부호 없는 16진 문자열로 변환 (x는 0123456789abcdef, X는 0123456789ABCDEF) |
b |
정수를 부호 없는 2진 문자열(0과 1)로 변환 |
c |
정수를 그 유니코드 문자로 변환 |
s |
변환 없이 문자열 그대로 삽입 |
f |
xx.yyy 형태의 부호 있는 십진 문자열로 변환 (y 개수는 정밀도, 기본 6; 정밀도 0이면 소수점 생략) |
e / E |
x.yyye±zz 형태의 과학 표기 (정밀도 기본 6; E를 쓰면 e 대신 E 출력) |
g / G |
지수가 -4보다 작거나 정밀도 이상이면 %e/%E로, 그 외엔 %f로 변환. 끝의 0과 소수점은 제거 |
% |
변환 없이 %를 삽입 |
ANSI sprintf와의 차이
- Tcl은 항상 유니코드 문자로 처리한다는 점을 보장해요.
%p와%n지정자는 지원되지 않아요.%c변환은 인자가 정수여야 하고 그 값을 대응 문자로 변환해요.- 부동소수 값을 포매팅할 때 크기 수정자는 무시돼요.
ll수정자와b지정자는 sprintf에 대응이 없어요.
예제
유니코드 숫자 값을 그 문자로 변환해요:
set value 120
set char [format %c $value]
time의 출력을 초 단위로 바꿔 백분의 일 초 정밀도로 출력해요:
set us [lindex [time $someTclCode] 0]
puts [format "%.2f seconds to execute" [expr {$us / 1e6}]]
X11 리터럴 색상 명세를 만들어요 (각 성분은 0..255):
set color [format "#%02x%02x%02x" $r $g $b]
XPG3 형식 코드로 데이터 순서를 바꾸지 않고 필드 순서를 재배치해요(로컬라이즈된 메시지 카탈로그에서 자주 쓰는 기법):
set fmt1 "Today, %d shares in %s were bought at $%.2f each"
puts [format $fmt1 123 "Global BigCorp" 19.37]
set fmt2 "Bought %2\$s equity ($%3$.2f x %1\$d) today"
puts [format $fmt2 123 "Global BigCorp" 19.37]
3의 거듭제곱 작은 표를 출력해요:
set w1 5
set w2 10
set sep +-[string repeat - $w1]-+-[string repeat - $w2]-+
puts $sep
puts [format "| %-*s | %-*s |" $w1 "Index" $w2 "Power"]
puts $sep
set p 1
for {set i 0} {$i<=20} {incr i} {
puts [format "| %*d | %*ld |" $w1 $i $w2 $p]
set p [expr {wide($p) * 3}]
}
puts $sep
더 알아보기
scan으로 문자열을 값으로 파싱 —format의 역연산string명령어로 문자열 다루기