Tcl Part I · Module 5 · Strings
The string Command and Its Subcommands
Most of the work a real script does is text handling, and Tcl puts almost all of it behind a single command. That is unusual enough to be worth a short chapter on its own, because it changes how you look things up: there is no object with methods to explore, there is one command whose first argument says what you want done. This chapter maps the whole set, shows you how to ask the interpreter for the list rather than reaching for documentation, and flags the one thing that catches people out — which argument goes first.
Foundation10 min readTclPart IStringsReference
Part I · Module 5 · Chapter 5.1 · The string Command and Its Subcommands
1. One Command, Many Jobs
set s " Report Draft "
puts "length -> [string length $s]"
puts "toupper -> [string toupper $s]"
puts "trim -> <[string trim $s]>"length -> 16
toupper -> REPORT DRAFT
trim -> <Report Draft>Three different operations, one command name. The second word — length, toupper, trim — says which one.
2. Why It Looks Like That
In Python you would write s.upper(): the data first, then the operation. In Tcl the command name always comes first, because Chapter 2.1 established that every line is a command followed by its words. There is no object to hang a method on.
So string is a command that dispatches on its first argument:
string toupper $s
│ │ │
│ │ └── the data
│ └───────── which operation
└───────────────── the commandTcl calls this shape an ensemble — one command name grouping related operations. You have already met others: file, info, and clock all work the same way. Recognising the shape means you can guess at file and info without being taught them.
3. The Whole Set
Grouped by what they do, with the chapter that covers each:
| Subcommand | What it does | Chapter |
|---|---|---|
length | how many characters | 5.2 |
index | one character at a position | 5.3 |
range | a span of characters | 5.3 |
first last | position of a substring | 5.4 |
match | test against a glob pattern | 5.5 |
equal compare | compare two strings | 5.6 |
toupper tolower totitle | change case | 5.7 |
trim trimleft trimright | remove edge characters | 5.8 |
replace map | substitute text | 5.9 |
is | test what a value looks like | 3.5 |
repeat | repeat a string | this chapter, §6 |
reverse | reverse a string | this chapter, §6 |
wordstart wordend | word boundaries around a position | rarely needed |
bytelength | storage size in bytes | 5.2 |
Two things in this module are not string subcommands, which is worth knowing now so you do not go looking: append, format, scan, split and join are commands in their own right. They get chapters 5.10 to 5.13.
4. Ask the Interpreter
Do not memorise that table. Ask for it:
puts [catch {string bogus x} message]
puts $message1
unknown or ambiguous subcommand "bogus": must be bytelength, compare, equal, first, index, is, last, length, map, match, range, repeat, replace, reverse, tolower, totitle, toupper, trim, trimleft, trimright, wordend, or wordstartDeliberately use a subcommand that does not exist, and Tcl lists every one that does.
This is faster than opening documentation and it is always right for the interpreter you are actually running. It works on every ensemble command:
catch {file bogus} m
puts "file: [string range $m 0 70]..."
catch {info bogus} m
puts "info: [string range $m 0 70]..."file: bad option "bogus": must be atime, attributes, channels, copy, delete, ...
info: unknown or ambiguous subcommand "bogus": must be args, body, cmdcount, ...The exact wording differs between commands — some say bad option, others unknown or ambiguous subcommand — but every one of them lists what it does accept.
5. Which Argument Goes First
The one genuine inconsistency, and the reason the usage line matters.
Most subcommands take the string first:
string length $text
string toupper $text
string range $text 0 5But the searching and matching ones do not:
string first ":" $text ;# what to find, then where to look
string match "*.txt" $text ;# the pattern, then the stringstring first takes the needle before the haystack, and string match takes the pattern before the subject. If a search is returning -1 when you are sure the text is there, check the argument order before anything else.
The fix is not memorisation. It is the usage line:
catch {string first} m ; puts $m
catch {string match} m ; puts $mwrong # args: should be "string first needleString haystackString ?startIndex?"
wrong # args: should be "string match ?-nocase? pattern string"Tcl names the arguments for you — needleString, haystackString, pattern, string.
6. Two Small Ones With No Chapter
puts [string repeat "-" 20]
puts [string repeat "ab" 3]
puts [string reverse "stressed"]--------------------
ababab
dessertsstring repeat is genuinely useful for separator lines in reports. string reverse comes up rarely, and mostly in puzzles.
7. Everything Returns a New String
No string subcommand changes its argument:
set s "hello"
string toupper $s
puts "after toupper: $s"
set s [string toupper $s]
puts "after assigning: $s"after toupper: hello
after assigning: HELLOThe first string toupper computed HELLO, returned it, and the script discarded it — Chapter 1.5 §3. To keep a result you must store it.
The one exception in this module is append, which does modify a variable — Chapter 5.10.
8. Common Mistakes
Looking for a method on the string. There is no object. The command comes first.
Forgetting to store the result. §7. Nothing is modified in place.
Getting the argument order wrong on first and match. §5. Read the usage line.
Memorising the subcommand list. §4. Ask for it.
Expecting split or format to be string subcommands. They are separate commands. §3.
9. Exercises
Exercise 1 — get the list. Run string bogus and read the subcommands. Pick three you have not seen and guess what they do, then check with the usage-line trick.
Exercise 2 — three operations. On the text " Draft Report ", produce its length, an uppercase version, and a trimmed version — storing each result.
Exercise 3 — argument order. Without running, write the correct call for: finding the position of "-" in a variable name; testing whether name ends in .log. Then check both with the usage lines.
Exercise 4 — the discovery habit elsewhere. Use the same trick on clock and on info. How many subcommands does each have?
Exercise 5 — a separator line. Print a 40-character line of =, then a heading, then the line again, using string repeat.
Exercise 6 — prove nothing changes. Write three lines that show a string subcommand leaving its input untouched, then the version that keeps the result.
10. Remember
stringis one command with about twenty subcommands, not methods on an object.- The operation comes second:
string toupper $text. - This shape is called an ensemble, and
file,infoandclockwork the same way. - Ask for the subcommand list with a deliberately wrong one:
string bogus. - Ask for a subcommand's arguments by calling it with none.
string firstandstring matchtake the needle or pattern first. Check this before debugging anything else.- Nothing is modified in place. Store the result.
append,format,scan,splitandjoinare separate commands, covered later in this module.
Next: the simplest subcommand, and the one question it raises about what a character is.
Where this fits
Part of the Tcl curriculum.
