55

If I have just entered the following command in Bash:

echo foo

I can change foo to bar by typing:

^foo^bar

Which results in the following command being executed:

echo bar

Now if I enter:

echo foo foo

Is there a way to change both instances of foo to bar just by using the caret (^) operator?

Additionally, are there man pages for shell operators like ^? man ^ results in "No manual entry for ^".

Benjamin W.
  • 46,058
  • 19
  • 106
  • 116
mattjames
  • 1,636
  • 1
  • 12
  • 14
  • 2
    Thanks for the answers, was hoping for a way to use the ^ syntax for duplicates since it is something I can remember more easily but looks like I will have to memorize the line noise version. – mattjames Jan 27 '10 at 19:12
  • 1
    It might be easier for you to remember the "line noise" version if you also think of `^string1^string2` as already being equivalent to `!!:s/string1/string2/`. – isomorphismes Jan 03 '13 at 18:45
  • @mattjames if you want something easier to remember, you can check out my answer, which is less "line noise"-y – MLP Aug 17 '17 at 22:55

6 Answers6

72

That particular feature is called quick substitution; its documentation can be found in the Event Designators section of the Bash Manual. You can't do what you want with quick substitution; you'll have to resort to something slightly more verbose:

!!:gs/foo/bar/
Adam Rosenfield
  • 390,455
  • 97
  • 512
  • 589
40

Nor sure how to do it with caret substitution, but here's how you do it with history:

!!:gs/foo/bar/

Let me break that down:

!! - reruns the last command. You can also use !-2 to run two commands ago, !echo to run the last command that starts with echo

:gs says to do a global (all instances) search/replace. If you wanted to just do replace the first instance, you would use ':s'

Finally, /foo/bar/ says to replace foo with bar

Community
  • 1
  • 1
R Samuel Klatchko
  • 74,869
  • 16
  • 134
  • 187
27

Try:

^foo^bar^:&

As you know ^foo^bar^ performs just one substitution, and the :& modifier repeats it.

LarsH
  • 27,481
  • 8
  • 94
  • 152
FlatEarther
  • 379
  • 3
  • 2
  • 10
    This will execute two substitutions but not a global substitution. – isomorphismes Jan 03 '13 at 19:14
  • 4
    I discovered that you could pass in multiple ":&" modifiers to the caret substitution. So the ":&" means again, and ":&:&" means again twice, and so on. (Repeating :& for every repetition will become tedious, and I'm glad to learn about !!:gs//. – rickumali Oct 19 '16 at 14:41
6

Caret substitution and other similar shortcuts are found in the Event Designators subsection of the HISTORY EXPANSION section of the bash(1) man page.

Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
1

If you're looking for something less difficult to memorize that accomplishes the same thing as the above !!:gs/foo/bar/, you could always create a function in your .bash_profile start-up script. I chose replace().

replace() {
    eval $(echo $(fc -ln -1) | eval "sed 's/${1}/${2}/g'") #compact form
}

OR, Less convolutedly

replace() {
    string=$(fc -ln -1) #gets last command string
    repcmmd="sed 's/${1}/${2}/g'" #build replacement sed command from fn input
    eval $(echo $string | eval $repcmmd) #evaluates the replacement command
}

Then the replace all can be made with

echo foo foo
replace foo bar
MLP
  • 106
  • 4
0
^word^  ........... erase word
^word^^ ........... delete everything until the end of the line
SergioAraujo
  • 11,069
  • 3
  • 50
  • 40