Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

command line word replacement

410 views
Skip to first unread message

thunde...@gmail.com

unread,
Sep 1, 2007, 6:09:13 PM9/1/07
to
Hello

I'd like to replace a word in my most recent command with a new word.

For example, I just ran

> scp -r local_dir_A/ mydomain.com:directory/

and now I want to do

> scp -r local_dir_B/ mydomain.com:directory/

I can do it with a substitution, but it requires actually explicitly
typing "local_dir_A" again:

> ^local_dir_A^local_dir_B^

Is there some quick way to tell the substitution to use the 2nd
argument of the previous command?

After reading documentation, I've tried the following:

> ^:2^local_dir_B^
> ^2-2^local_dir_B/^
> ^!!2-2^local_dir_B^
> ^!2^local_dir_B^
> ^!2-2^local_dir_B^
> !!:s%:2%local_dir_B/%
> !:s%:2%local_dir_B%
> !:s%!:2%local_dir_B%

These all result in "substitution failed"

Any help is appreciated.

Thanks in advance!

- Rob

William Pursell

unread,
Sep 2, 2007, 12:13:28 AM9/2/07
to
On Sep 1, 6:09 pm, thunderrab...@gmail.com wrote:

> I'd like to replace a word in my most recent command with a new word.
>
> For example, I just ran
>
> > scp -r local_dir_A/ mydomain.com:directory/
>
> and now I want to do
>
> > scp -r local_dir_B/ mydomain.com:directory/

Responding on a machine with no bash, so unable to test,
and this is not exactly what you're looking for, but
I would do that (with readline set to vi key-bindings):
<esc>kfArB

(or, slightly longer and more explicit):
<esc>k2WcfAlocal_dir_B

I realize you're looking for a substitution, but
I find it's usually easier to do this sort of thing.
With emacs key-bindings, you can do something
similar, but you'll probably have to resort to using the
arrow keys to get the cursor in the right place.

thunde...@gmail.com

unread,
Sep 2, 2007, 8:10:23 AM9/2/07
to
> I would do that (with readline set to vi key-bindings):
> <esc>kfArB
>
> (or, slightly longer and more explicit):
> <esc>k2WcfAlocal_dir_B

Thanks for the ideas; I use emacs bindings, but I can basically see
you've perfectly answered my question.

However, I wrote "local_dir_A" and "local_dir_B" to simplify the
question. The names were actually "escalators" and "line_signs" and
"lower_fire_exit" respectively.

In the actual cases that I wanted to do, it looks like the command
above would require typing the old words in order to explicitly
identify and replace them.

For now I can continue with the equivalent expression using emacs
bindings. But if anyone can give the syntax for a replacement that
doesn't require typing the old word, that would be great great great.

Just to be clear on my attempts above:

> ^:2^local_dir_B^
> ^2-2^local_dir_B/^
> ^!!2-2^local_dir_B^
> ^!2^local_dir_B^
> ^!2-2^local_dir_B^
> !!:s%:2%local_dir_B/%
> !:s%:2%local_dir_B%
> !:s%!:2%local_dir_B%

I'm trying to tell the replace command to use the 2nd word as the
first item to replace.

Alan D. Salewski

unread,
Sep 7, 2007, 4:38:55 AM9/7/07
to

You can certainly do this using a number of different key sequences.

The core of the solution involves using the readline function
`yank-nth-arg' with a numeric argument:

$ echo foo bar baz quux
foo bar baz quux
$ !!:s/baz/junk
echo foo bar junk quux
foo bar junk quux

The third line above was typed like this:

! ! : s / M-3 C-M-y / j u n k RET

I have C-M-y bound to `yank-nth-arg' via this setting in my
${HOME}/.inputrc file (though bash(1) indicates that this is the
default binding):

Control-Meta-y: yank-nth-arg

The M-3 (which is bound to the readline function `digit-argument')
simply provides the argument of '3' to `yank-nth-arg' to select 'baz'
for the field to be replaced.

Note that the arguments from the previous command line are zero
indexed; using M-0 instead of M-3 would have replaced 'echo' instead of
'baz'; likewise, using M-4 instead of M-3 would have replaced 'quux'.

The other ways to do this simply involve variations on the above: use
the ESC as a prefix key instead of Meta, and invoke the
`universal-argument' readline function instead of `digit-argument'. In
my ${HOME}/.inputrc file I aslo have this binding:

Control-Meta-u: universal-argument

So the remaining variations of the above are:

! ! : s / ESC 3 C-M-y / j u n k RET
! ! : s / ESC 3 ESC C-y / j u n k RET
! ! : s / C-M-u 3 C-M-y / j u n k RET
! ! : s / C-M-u 3 ESC C-y / j u n k RET

HTH,
-Al

P.S. As an aside, my early tests in 'xterm' version 222-1etch2 on my
Debian box, I was initially only able to get the above examples to
work when 'xterm' was launched with LANG=C, but not with
LANG=en_US.UTF-8. With the latter tests, only those key sequences
that used ESC to obtain the numeric argument were working. By
contrast, all examples worked as expected on the Linux console.

A bit of googling turned up the "Meta keys and locales" section in
this:
http://www.astro.caltech.edu/~mcs/tecla/tecla.html

I needed to add the following to my ${HOME}/.Xresources:

XTerm*metaSendsEscape: true

--
-----------------------------------------------------------------
a l a n d. s a l e w s k i sale...@worldnet.att.net
1024D/FA2C3588 EDFA 195F EDF1 0933 1002 6396 7C92 5CB3 FA2C 3588
-----------------------------------------------------------------

Rob Nugen

unread,
Sep 7, 2007, 10:09:11 PM9/7/07
to
> The core of the solution involves using the readline function
> `yank-nth-arg' with a numeric argument:
>
> $ echo foo bar baz quux
> foo bar baz quux
> $ !!:s/baz/junk
> echo foo bar junk quux
> foo bar junk quux
>
> The third line above was typed like this:
>
> ! ! : s / M-3 C-M-y / j u n k RET
>

I am thrilled to say that the above sequence worked with zero
modification to any setup on my machine. Actually I typed

^ M-3 M-C-y ^ n e w ^ RET

I'm running OS X 10.4.1

Thank you for the huge level of detail in your answer. I cannot
honestly say I understand it all, nor will I realistically use it, but
I hope your answer solves problems for millions of people.

It may take a while with the rate of posts on this group. ;-)

- Rob

0 new messages