Tcl의 리스트

admin의 아바타

리스트는 Tcl의 편리한 데이타 구조중의 하나입니다. 리스트란 중 괄호 또는 쌍따옴표("")를 사용한 공백으로 구분된 문자열의 집합입니다. 아래는 리스트를 작성한 예제이며, 두 결과는 같습니다.

% set var {사과 귤 바나나}
사과 귤 바나나
% set var "시과 귤 바나나"
시과 귤 바나나

list, concat, lappend

list 커맨드는, 인자의 문자열로부터 리스트를 생성합니다.

% set var [list 사과 귤 바나나]
사과 귤 바나나
% set var
사과 귤 바나나

단 인자의 중간에 특수 문자가 있다면, 중 괄호로 싸줍니다.

set var [list \$ \[ abc\ xyz]
{$} {[} {abc xyz}

concat 커맨드는 인자의 문자열로부터 공백을 기준으로 리스트를 생성합니다.

set var [concat "사과 귤 바나나"]
사과 귤 바나나
set var [concat {사과 귤 바나나}]
사과 귤 바나나

lappend 커맨드는 리스트에 요소를 추가합니다. lappend 커맨드는, 지정된 변수가 존재 하지 않으면 새로운 리스트를 생성합니다.

set var {사과 귤 바나나}
사과 귤 바나나
lappend var 멜론 딸기
사과 귤 바나나 멜론 딸기

llength, lindex, lrange

llength 커맨드는 리스트의 요소 갯수를 돌려줍니다.

% set var {사과 귤 바나나}
사과 귤 바나나
% llength $var
3

lindex 커맨드는, 리스트의 지정된 인덱스 요소를 돌려줍니다. 인덱스는 0부터 시작합니다.

% set var {사과 귤 바나나}
사과 귤 바나나
% lindex $var 1

lrange 커맨드는 리스트의 지정된 범위의 요소를 리스트로 돌려줍니다.

% set var {사과 귤 바나나}
사과 귤 바나나
% lrange $var 0 1
사과 귤

linsert, lreplace

linsert는 리스트의 지정된 인덱스에 요소를 삽입한 리스트를 돌려줍니다.

% set var {사과 귤 바나나}
사과 귤 바나나
% linsert $var 1 멜론 딸기
사과 멜론 딸기 귤 바나나

lreplace는 리스트의 지정된 인덱스의 요소를 치환한 리스트를 돌려줍니다.

% set var {사과 귤 바나나}
사과 귤 바나나
% lreplace $var 1 2 딸기 멜론
사과 딸기 멜론

lreplace를 응용하면 리스트의 지정된 인덱스의 요소를 삭제한 리스트를 돌려주는 것도 할수 있습니다.

% set var {사과 귤 바나나}
사과 귤 바나나
% lreplace $var 1 1
사과 바나나

lset

lset 커맨드는 지정된 인덱스의 요소를 직접 변경합니다. (Tcl 8.4 버전에서 추가)

% set var {사과 귤 바나나}
사과 귤 바나나
% lset var 1 메론
사과 메론 바나나
% set var
사과 메론 바나나

인덱스를 생략한 경우에는 리스트를 재작성합니다. lset 커맨드는 변수를 새로이 작성할수 없는 점이 set과 다릅니다.

% set var {사과 귤 바나나}
사과 귤 바나나
% lset var 메론
메론
% lset var2 메론
can't read "var2": no such variable

리스트의 리스트의 경우에는 인덱스를 여러개 지정하여 변경할수 있습니다.

% set var {{사과 귤 바나나} {배 감자 메론}}
{사과 귤 바나나} {배 감자 메론}
% lset var 1 1 메론
{사과 귤 바나나} {배 메론 메론}

lsearch

lsearch 커맨드는 리스트의 요소를 검색합니다. 요소가 발견되면, 요소의 인덱스를 리턴하고, 발견되지 않으면 -1을 리턴합니다.

% set var {사과 귤 바나나}
사과 귤 바나나
% lsearch $var 바나나
2
% lsearch $var 감자
-1

-glob 또는 -regexp 옵션을 사용하면 정규표현식을 사용하여 검색할 수 있습니다.

% set var {사과 귤 바나나}
사과 귤 바나나
% lsearch -glob $var "바*"
2
% lsearch -regexp $var "바+"
2

lsort

lsort 커맨드는 리스트의 요소를 정렬합니다. 아래는 옵션입니다.

  • -ascii: 아스키 코드 순서로 정렬 (기본)
  • -dictionary: 사전 순서로 정렬
  • -integer: 정수로 정렬
  • -real: 부동소수점으로 정렬
  • -increasing: 올림 정렬
  • -decreasing: 내림 정렬
  • -index: index 요소가 리스트인 경우, 정렬 대상의 인덱스를 지정
  • -unique: 중복된 요소를 제거

% set var {사과 귤 바나나}
사과 귤 바나나
% lsort -dictionary $var
귤 바나나 사과
% set var {{1 사과} {2} {3 바나나}}
{1 사과} {2} {3 바나나}
% lsort -decreasing -integer -index 0 $var
{3 바나나} {2} {1 사과}
% lsort -increasing -integer -index 0 $var
{1 사과} {2} {3 바나나}
% set var {사과 귤 바나나 사과}
사과 귤 바나나 사과
% lsort -unique $var
귤 바나나 사과

split, join

split 커맨드는 지정된 단락 문자로 문자열을 분할하여 리스트로 리턴합니다. 단락 문자를 생략한 경우는 공백을 기준으로 분할 할 것입니다.

% set var {사과:귤:바나나:사과}
사과:귤:바나나:사과
% split $var :
사과 귤 바나나 사과

join 커맨드는, split의 반대로 이하와 같습니다.

% set var {사과 귤 바나나 사과}
사과 귤 바나나 사과
% join $var :
사과:귤:바나나:사과

리스트는 상당히 편리한 커맨드입니다. 리스트 커맨드와 닮은 커맨드가 있기 때문에 정리해 보겠습니다.

list와 concat

list와 concat 커맨드는 비슷합니다. 약간의 차이가 있기 때문에 주의해야 합니다. 아래의 예를 비교해 보면, concat는 리스트 레벨을 1개만 제거합니다.

% list a b {c d e} {f {g h}}
a b {c d e} {f {g h}}
% concat a b {c d e} {f {g h}}
a b c d e f {g h}

eval 과의 조합

eval 커맨드는 인자를 커맨드로서 실행하는 커맨드이지만, concat 과 깉이 리스트 레벨을 1개만 제거합니다. eval과 concat 를 조합하면 리스트 레벨을 2개 제거합니다.

% eval list a b {c d e} {f {g h}}
a b c d e f {g h}
% eval concat a b {c d e} {f {g h}}
a b c d e f g h

subst와 쌍따옴표("")

subst 커맨드와 쌍따옴표 커맨드도 커맨드 전개과 변수 전개을 한다는 의미에서는, concat과 같이 리스트 레벨을 1개만 제거합니다. subst 커맨드는, 인자를 커맨드로써 실행하지 않는 점만 제외하면 eval과 같습니다.

list

% set x {1 2}
1 2
% set y [list $x 3]
{1 2} 3

concat

% set x {1 2}
1 2
% set y [concat $x 3]
1 2 3

subst

% set x {1 2}
1 2
% subst {$x 3}
1 2 3

쌍따옴표("")

% set x {1 2}
1 2
% set y "$x 3"
1 2 3

주의

list와 concat 커맨드는 데이타에 의해서 같은 결과를 리턴하는 경우가 있습니다. 특히 list, concat, eval, subst, 쌍따옴표를 조합해서 사용 한다면 결과를 예측하기 어려워지고, 이것에 의해 스크립트에 버그가 생길 우려가 있기 때문에 충분히 주의 해서 사용해야 할것입니다.