Question
Let's say I just entered this command to get a count of how many lines contain a particular string:
me@machine $ command-producing-multi-line-output | grep -i "needle" | wc -l
Now how could I quickly replace "needle"
with some other word?
Current Inefficient Solution
Right now I:
- Press
Up
on the keyboard to load the last command. - Press
Left
orCtrl
+Left
until I reach"needle"
. - Press
Backspace
orCtrl
+w
to delete the word. - Type or paste in the new word.
- Hit
Enter
.
This seems pretty inefficient.
Attempted Non-working Solutions
I've tried to research history shortcuts like !!:sg/needle/new-needle
; but there are a few problems with this:
- You can't press
Up
to put!!:sg/needle/new-needle
back on the command line. Doing this will just show what it expands to (running right back into the original problem). - Repeating this with yet another new needle requires you to replace both
needle
andnew-needle
(i.e.!!:sg/new-needle-from-before/yet-another-new-needle
). - You need to type the entire
needle
instead of using something like!:4
or$4
(i.e.!!:sg/!:4/new-needle
or!!:sg/$4/new-needle
) to save time/keystrokes on however long the needle was.
I've also found things like !:^-3 "new-needle" !:5-$
but that also has issues:
- It expands in history so it can't be re-used quickly.
- Even if it didn't expand, you run into the original problem of needing to replace a word in the middle of a command chain.
I believe there has to be some super fast way to do what I want to do, and that some linux gurus out there know it. I would be very grateful for any input or suggestions on this.
EDIT:
Background
Just a bit of background, I work a lot with OpenStack on the command line and I find myself often needing to replace a parameter in several places within a long command chain of piped commands.
The way our OpenStack environments are configured, several engineers share a single stack
user on any number of servers, and there are several clusters within multiple environments. So a function declared within .bashrc
or .profile
file isn't really possible.
I'm hoping for something portable that can be used quickly with no or very minimal setup required. Otherwise I may just need to resort to using a solution outside of the shell entirely (such as clipboard replacement in AutoHotKey/Keyboard Maestro/AutoKey, etc.).
Best Answer
I've run into a similar situation and present my solution here just in case it's a useful pattern.
Once I realize that I'm repeatedly changing one piece of data that's annoying to replace interactively, I'll stop and write a little
while
loop:Up-Arrow to the previous
command-producing-multi-line-output
line and replace"haystack"
with"$needle"
(ending with Control+D)
Or the slightly fancier variation:
If I see a future for this command-line beyond "today", I'll write it into a function or script.