3

I'm used to typing !! in bash when I want to reference the last command executed in that shell.

$ ls -la  
drwxr-xr-x   4 me  wheel    136 Jan 19  2013 wireshark_stuff  
... (etc) ...  
-rw-r--r--   1 me  wheel     11 Mar 13 13:51 old_PS1  
$ !! |grep for_something_in_those_results  
ls -la |grep for_something_in_those_results  
/grep_results

Is there a way to do this in python?

>>> complicated_dict.['long_key_name'][0]  
(response)  
>>> my_func(!!) 

This would get really handy as the interpreter commands become increasingly complicated. Sure, I could just use a plethora of local variables - but sometimes it's handy to just invoke the last thing run...

poke
  • 369,085
  • 72
  • 557
  • 602
user3.1415927
  • 367
  • 3
  • 19
  • 2
    Underscore works in the shell for this purpose. – user3483203 Mar 22 '18 at 17:45
  • Good Lord you people are fast. – user3.1415927 Mar 22 '18 at 17:47
  • 1
    Underscore doesn't reexecute anything, though; it's just a variable bound to the value of the previous expression. – chepner Mar 22 '18 at 17:48
  • @poke; Definitely the same answer, but the referenced potential dupe refers to Matlab/Mathematica. I recommend leaving this here to route bash-familiar users like myself to the accepted answer there. (I will also accept the first answer here, which I commented on below, when I am able.) – user3.1415927 Mar 22 '18 at 17:50
  • @chepner Good to know, as bash (I believe) actually evaluates `!!` to the content of the last executed command. A good nuance to understand - thanks. – user3.1415927 Mar 22 '18 at 17:51
  • @user3.1415927 Don’t worry, a question being closed as a duplicate does not mean that it’s not useful or otherwise wrong. It just means that it has already been covered elsewhere; closed questions are usually kept around as an additional entry point to a topic, so yeah, we’ll keep this :) – poke Mar 22 '18 at 17:52
  • It does; `!!` is part of history expansion, so it really just expands to the last *command*, and (by default) executes it. (I have the option to just display the command in the buffer, but that's beside the point.) I think there is a Readline function that will fetch and execute the last command, but I have to research it a little. – chepner Mar 22 '18 at 17:53
  • I’d say the `_` is more similar to accessing the exit code of the previous command. Output in shells is usually produced by printing to the stdout. That content is of course no longer accessible; same as printed content in Python. – poke Mar 22 '18 at 17:55
  • To be clear then, `_` doesn't actually reference the last executed expression, but rather the output/return of the last executed expression? If that's the case, then technically `_` is not the same as `!!` - it references the outcome, not the input.... I would still like to know if there is something to do the same history expansion as is performed in bash when `!!` is invoked. – user3.1415927 Apr 04 '18 at 17:52

4 Answers4

4

The value of the last expression evaluated in the Python shell is available as _, ie the single underscore.

Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
4

You can use the _ character to reference the last calculated value, and use it in other calculations:

>>> x = 5
>>> x + 10
15
>>> _
15
>>> _ + 2
17
user3483203
  • 50,081
  • 9
  • 65
  • 94
1

Using default Readline bindings, Control-P + Enter is probably the closest exact equivalent to !!; the first key fetches the previous command; the second executes it. You can probably add a custom binding to .inputrc to execute both functions with one keystroke. Note, though, this is entirely line-oriented; if you try to use this following a multi-line for statement, for example, you'll only get the very last line of the body, not the entire for statement.

The _ variable stores the result of the last evaluated expression; it doesn't reevaluate, though. This can be seen most clearly with something like datetime.datetime.now:

>>> datetime.datetime.now()
datetime.datetime(2018, 3, 22, 14, 14, 50, 360944)
>>> datetime.datetime.now()
datetime.datetime(2018, 3, 22, 14, 14, 51, 665947)
>>> _
datetime.datetime(2018, 3, 22, 14, 14, 51, 665947)
>>> _
datetime.datetime(2018, 3, 22, 14, 14, 51, 665947)
>>> _
datetime.datetime(2018, 3, 22, 14, 14, 51, 665947)
>>> datetime.datetime.now()
datetime.datetime(2018, 3, 22, 14, 14, 58, 404816)
chepner
  • 497,756
  • 71
  • 530
  • 681
0

Up-arrow / return! As long as your interpreter was compiled with readline support.

Chris Johnson
  • 20,650
  • 6
  • 81
  • 80