开发者

How can I replace ALL instances of a string in the previous command in Bash? [duplicate]

开发者 https://www.devze.com 2022-12-18 02:30 出处:网络
This question already has answers here: ^word^replacement^ on all matches in Bash? (6 answers) Closed last year.
This question already has answers here: ^word^replacement^ on all matches in Bash? (6 answers) Closed last year.

If I have just entered the following command in Bash:

开发者_JS百科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 ^".


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/


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


Try:

^foo^bar^:&

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


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


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


^word^  ........... erase word
^word^^ ........... delete everything until the end of the line
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号