1

This is a quite simple question that I can't find an answer to.

I have a string such as "ASDGFasd#!dasd" which I would like to enter into the command line as an argument e.g.

python test.py "ASDGFasd#!dasd"

This does not run test.py with the string provided (as I want it to), but instead returns:

bash: !dasd: event not found

How do solve this?

I am using ubuntu 14.04 LTS with python 2.7

mklement0
  • 382,024
  • 64
  • 607
  • 775
Rorschach
  • 3,684
  • 7
  • 33
  • 77
  • 2
    Try single quotes instead of double? – Tom Zych Nov 13 '15 at 03:03
  • Yep, that did it, if you make that comment into an answer I will accept it. – Rorschach Nov 13 '15 at 03:05
  • 3
    That's history expansion biting you. You can use single quotes as TomZych said or disable it. This should not be a problem in a script (as history expansion is disabled in non-interactive shell sessions by default). – Etan Reisner Nov 13 '15 at 03:05
  • Go ahead and take the answer, @Etan. You knew what it was, I only knew how to avoid it. – Tom Zych Nov 13 '15 at 03:06
  • 1
    Yeah but good luck finding either of these if you don't know it's history expansion :) I'll change the title to reflect the error message, making this more searchable. – Tom Zych Nov 13 '15 at 03:08
  • 1
    A couple more: [29744748](http://stackoverflow.com/questions/29744748) [26443880](http://stackoverflow.com/questions/26443880). – Tom Zych Nov 13 '15 at 03:12

1 Answers1

7

I'll attempt a summary of existing answers to similar questions:

  • ! is expanded by bash as part of the history expansion feature, which is by default on in interactive shells, but off by default in scripts (non-interactive shells).

    • Specifically, ! together with the following characters is interpreted as an expression that recalls a previous command; e.g., !! recalls the most recently executed command, and !l recalls the most recently executed command starting with l.
  • An easy way to avoid expansion of ! altogether is to turn history expansion off, which is advisable, given that the feature can be disruptive and given that the readline library's features, which were introduced later, are a superior replacement.

    • To turn history expansion off, add set +H (or set +o histexpand) to your ~/.bashrc file (or ~/.bash_profile file on OS X) - this is recommended in the highest-voted answer to "-bash: !": event not found"
    • An alternative, though probably ill-advised, is to choose an alternative character for history expansion, by setting the special histchars shell variable to the desired character.

With history expansion ON, ! is expanded:

  • always:

    • in unquoted strings: echo hi!
    • in double-quoted strings, irrespective of embedded command substitutions: echo "hi!"
      • Note that this means that ! is even expanded inside a single-quoted string inside a command substitution embedded in a double-quoted string: apparently, history expansion occurs very early during parsing, before the internals of the double-quoted strings are parsed to recognize embedded command substitutions; e.g.: echo "$(echo 'hi!')" # '!' is still expanded(!) - this is the gist of question "How to escape history expansion exclamation mark ! inside a double quoted " command substitution like "$(echo '!b')"?"
      • Strictly speaking, ! parsing doesn't even respect double-quotes per se, and considers any run of non-whitespace characters following ! the history-expansion argument, including "; for instance, echo foo!" - despite imbalanced double-quotes - is considered a valid command, as is echo foo!bar"baz.
  • never:

    • in single-quoted strings: echo 'hi!'
mklement0
  • 382,024
  • 64
  • 607
  • 775