Search code examples
bashtclexpect

How to escape square brackets in expect?


I am not able to escape square braces in the expect script, the example as below,

I have a question.sh script as below,

#!/bin/bash
echo "Would you like to specify inputs and execute the script? [Y/n]"
read $REPLY

echo "Deleted Item with ID: 50 and do cleanup? [Y/n]"
read $REPLY

echo "Deleted Item with ID: 51 and do cleanup? [Y/n]"
read $REPLY

echo "Deleted Item with ID: 52 and do cleanup? [Y/n]"
read $REPLY

For the above question.sh I have the below answer.exp, and execute the same with 'expect answer.exp 51' command,

#!/usr/bin/expect -f

set timeout -1

spawn ./question.sh

set item "Deleted Item with ID: "
append item [lindex $argv 0]
append item " and do cleanup? \[Y/n\]"

expect "Would you like to specify inputs and execute the script? \[Y/n\]"
send -- "Y\r"

expect {

      $item {
            send "Y\r"
            exp_continue
      }
      " and do cleanup? \[Y/n\]" {
            send "n\r"
            exp_continue
      }
}

When ever I have the square braces involved the expect is not matching and does not send the answer (Y/N) back.

The same when I remove the square braces from the question and the answer scripts expect works fine, the changed question and answer scripts as below.

question.sh:

 #!/bin/bash
echo "Would you like to specify inputs and execute the script? Y/n"
read $REPLY

echo "Deleted Item with ID: 50 and do cleanup? Y/n"
read $REPLY

echo "Deleted Item with ID: 51 and do cleanup? Y/n"
read $REPLY

echo "Deleted Item with ID: 52 and do cleanup? Y/n"
read $REPLY

answer.exp:

#!/usr/bin/expect -f

set timeout -1

spawn ./question.sh

set item "Deleted Item with ID: "
append item [lindex $argv 0]
append item " and do cleanup? Y/n"

expect "Would you like to specify inputs and execute the script? Y/n"
send -- "Y\r"

expect {

      $item {
            send "Y\r"
            exp_continue
      }
      " and do cleanup? Y/n" {
            send "n\r"
            exp_continue
      }
}

Solution

  • The expect command matches against tcl string match style wildcard patterns by default, so [Y/n] is trying to match one of the characters Y, forward slash or n.

    Solutions:

    1. Add more backslashes:
    append item " and do cleanup? \\\[Y/n\\\]"
    

    so it turns into \[Y/N\].

    1. Use braces instead:
    append item { and do cleanup? \[Y/n\]}
    

    to prevent the substitution of backslashes.

    1. Tell expect to do an exact match by using the -ex option before each pattern:
    #!/usr/bin/expect -f
    
    set timeout -1
    
    spawn ./question.sh
    
    set item "Deleted Item with ID: "
    append item [lindex $argv 0]
    append item " and do cleanup? \[Y/n\]"
    
    expect -ex "Would you like to specify inputs and execute the script? \[Y/n\]"
    send -- "Y\r"
    
    expect {
    
          -ex $item {
                send "Y\r"
                exp_continue
          }
          -ex " and do cleanup? \[Y/n\]" {
                send "n\r"
                exp_continue
          }
    }