How can I replace ALL instances of a string in the previous command in Bash?
BashBash Problem Overview
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 ^".
Bash Solutions
Solution 1 - Bash
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/
Solution 2 - Bash
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
Solution 3 - Bash
Try:
^foo^bar^:&
As you know ^foo^bar^
performs just one substitution, and the :&
modifier repeats it.
Solution 4 - Bash
Caret substitution and other similar shortcuts are found in the Event Designators subsection of the HISTORY EXPANSION section of the bash(1)
man page.
Solution 5 - Bash
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
Solution 6 - Bash
^word^ ........... erase word
^word^^ ........... delete everything until the end of the line