Backslashes

Tcl makes various substitutions when you have backslashes, dollar signs, and brackets in command arguments. You should be familiar with these from Chapter 2 (p. 23). In this section, I am going to focus on backslashes.

Backslash translations are done by Tcl only when processing command arguments. For example, \n is translated to a linefeed, \[ is translated to a "[“, and \\ is translated to a "\“. Sequences that have no special translation are replaced by the character without the backslash. For example, \z is translated to a "z“.

While pattern matching, Expect uses these translated values. For example:

expect "\n" ;# matches \n (linefeed character)
expect "\r" ;# matches \r (return character)
expect "\z" ;# matches z  (literal z)
expect "\{" ;# matches {  (literal left brace)

If any backslashes remain after Tcl’s translation, the pattern matcher (i.e., pattern matching algorithm) then uses these remaining backslashes to force the following character into its literal equivalent. For example, the string "\\*" is translated by Tcl to "\*“. The pattern matcher then interprets the "\*" as a request to match a literal "*“.

expect "*"    ;# matches * and ? and X and abc
expect "\\*"  ;# matches * but not ? or X or abc

Similarly, backslashes prevent a ? from acting like a wildcard.

expect "?"    ;# matches * and ? and X but not abc
expect "\\?"  ;# matches ? but not * or X or abc

So that you can see the consistency here, I have written out some more examples. Do not try to memorize these. Just remember two rules:

  1. Tcl translates backslash sequences.

  2. The pattern matcher treats backslashed characters as literals.

These rules are executed in order and only once per command.

For example, in the second command below, Tcl translates the "\n" to a linefeed. The pattern matcher gets the linefeed and therefore tries to match a linefeed. In the third command, Tcl translates the "\\" to "\" so that the pattern matches sees the two characters "\n“. By the second rule above, the pattern matcher interprets this as a literal n. In the fourth command, Tcl translates "\\" to "\" and "\n" to a linefeed. By the second rule, the pattern matcher strips off the backslash and matches a literal linefeed.

In summary, \n is replaced with a linefeed by Tcl but a literal n by the pattern matcher. Any character special to Tcl but not to the pattern matcher behaves similarly.

expect "n" ;# matches n
expect "\n" ;# matches \n (linefeed character)
expect "\\n" ;# matches n
expect "\\\n" ;# matches \n
expect "\\\\n" ;# matches sequence of \ and n
expect "\\\\\n" ;# matches sequence of \ and \n
expect "\\\\\\n" ;# matches sequence of \ and n
expect "\\\\\\\n" ;# matches sequence of \ and \n
expect "\\\\\\\\n" ;# matches sequence of \, \, and n

In the next set of examples, \* is replaced with a literal * by Tcl and by the pattern matcher. Any character special to the pattern matcher but not Tcl behaves similarly.

expect "*" ;# matches anything
expect "\*" ;# matches anything
expect "\\*" ;# matches *
expect "\\\*" ;# matches *
expect "\\\\*" ;# matches \ followed by anything
expect "\\\\\*" ;# matches \ followed by anything
expect "\\\\\\*" ;# matches \ followed by *

The "[" is special to both Tcl and the pattern matcher so it is particularly messy. To match a literal "[“, you have to backslash once from Tcl and then again so that it is not treated as a range during pattern matching. The first backslash, of course, has to be backslashed to prevent it from turning the next backslash into a literal backslash!

expect "\\\["   ;# matches literal [

This is quite a headache. In fact, if the rest of the pattern is sufficiently specific, you may prefer to improve readability by just using using a ? and accepting any character rather than explicitly forcing a check for the "[“.

The next set of examples shows the behavior of "[" as a pattern preceded by differing numbers of backslashes. If the "[" is not prefixed by a backslash, Tcl interprets whatever follows as a command. For these examples, imagine that there is a procedure named XY that returns the string "n*“.

expect "[XY]" ;# matches n followed by anything
expect "\[XY]" ;# matches X or Y
expect "\\[XY]" ;# matches n followed by anything
expect "\\\[XY]" ;# matches [XY]
expect "\\\\[XY]" ;# matches \ followed by n followed ...
expect "\\\\\[XY]" ;# matches sequence of \ and X or Y

The \\[XY] case deserves close scrutiny. Tcl interprets the first backslash to mean that the second is a literal character. Tcl then interprets [XY] as the result of the XY command. The pattern matcher ultimately sees the four character string "\n*w“. The pattern matcher interprets this in the usual way. The backslash indicates that the n is to be matched literally (which it would even without the backslash since the n is not special to the pattern matcher). Then as many characters as possible are matched so that a w can also be matched.

By now, you may be wondering why I write all patterns in double quotes in preference to using braces. It is true that braces shorten some of the patterns I have shown here. However, braces do not allow patterns to be specified from variables, nor do they allow backslashed characters such as newlines. But such patterns occur so frequently that you have to be familiar with using double quotes anyway. Constantly thinking about whether to use braces or double quotes is unproductive. Learn how to use double quotes and do not think further about using braces for patterns. If you know Tcl very well and skippedChapter 2 (p. 23), it may be helpful for you to now go back and read the beginning of it as well as the discussion of eval on page 55.

Get Exploring Expect now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.