From: Thomas 'PointedEars' Lahn on
George wrote:

> I am a bit confused with the way bash history works. Say, for example,
> that I am running the following command:
>
> ls -l test1/
>
> Now, if I do not remember the name of the previous directory I used but
> now I want to run an ls on the directory test2, I try running:
>
> !!:s/!!:1:p/test2 (to get the command echoed without executing)
>
> but I am getting the message that substitution failed.

If I read the bash 4.1.5(1) manpage correctly (you have not told about he
version), !!:s/x/y/ substitutes x in the previous command with y. In your
case, x is `!!:1:p', which is substituted to `-l'. So, theoretically, the
resulting substitution should be `!!:s/-1/test2' and the result of that
would be `ls test2 test1/' (not what you want).

However, it appears you cannot use `!!' within the pattern:

$ !!s:/!!/x/
ls -l test1/s:/ls -l test1//x/
[...]

(not `x'.) Therefore,

$ !!:s/z/y
bash: :s/z/y/: substitution failed

(no `z' found in the previous command)


HTH

PointedEars
From: George on
On 02/06/2010 13:28, Thomas 'PointedEars' Lahn wrote:
> !!:s/x/y/ substitutes x in the previous command with y. In your
> case, x is `!!:1:p', which is substituted to `-l'. So, theoretically, the
> resulting substitution should be `!!:s/-1/test2' and the result of that
> would be `ls test2 test1/' (not what you want).
>
> However, it appears you cannot use `!!' within the pattern:
>
> $ !!s:/!!/x/
> ls -l test1/s:/ls -l test1//x/
> [...]

Hi PointedEars,

That was exactly my motivation for asking the question. I saw the
substitution pattern, but from my experiments it seems that (unless my
commands were wrong) regular expressions (or any other kind of patterns
than string literals) are not supported.

Could somebody please confirm (or dispute) this?

Regards,
George
From: Thomas 'PointedEars' Lahn on
George wrote:

> Thomas 'PointedEars' Lahn wrote:
>> !!:s/x/y/ substitutes x in the previous command with y. In your
>> case, x is `!!:1:p', which is substituted to `-l'. So, theoretically,
>> the resulting substitution should be `!!:s/-1/test2' and the result of
>> that would be `ls test2 test1/' (not what you want).
>>
>> However, it appears you cannot use `!!' within the pattern:
>>
>> $ !!s:/!!/x/
>> ls -l test1/s:/ls -l test1//x/
>> [...]
>
> That was exactly my motivation for asking the question. I saw the
> substitution pattern, but from my experiments it seems that (unless my
> commands were wrong) regular expressions (or any other kind of patterns
> than string literals) are not supported.
>
> Could somebody please confirm (or dispute) this?

That this applies follows from my example and the manpage:

| BASH(1) BASH(1)
| [...]
| HISTORY EXPANSION
| [...]
| Event Designators
| [...]
| !?_string_[?]
| Refer to the most recent command containing _string_. The trail‐
| ing ? may be omitted if _string_ is followed immediately by a new‐
| line.
| ^_string1_^_string2_^
| Quick substitution. Repeat the last command, replacing _string1_
| with _string2_. Equivalent to ``!!:s/_string1_/_string2_/'' (see
| *Modifiers* below).
| [...]
| Modifiers
| After the optional word designator, there may appear a sequence of
| one or more of the following modifiers, each preceded by a `:'.
| [...]
| s/_old_/_new_/
| Substitute _new_ for the first occurrence of _old_ in the event
| line. Any delimiter can be used in place of /. The final
| delimiter is optional if it is the last character of the event
| line. The delimiter may be quoted in _old_ and _new_ with a single
| backslash. If & appears in _new_, it is replaced by _old_. A sin‐
| gle backslash will quote the &. If _old_ is null, it is set to
| the last _old_ substituted, or, if no previous history substitu‐
| tions took place, the last string in a !?_string_[?] search.
| [...]
| GNU Bash-4.1 2009 December 29 BASH(1)

However, you do not need !!:s/x/y here:

$ ls -l test/
[...]
$ !!:0-1 test2/
ls -l test2/
[...]
$ ls -l -a test/
[...]
$ !!:0- test2/
ls -l -a test2/
[...]


HTH

PointedEars
From: George on
On 03/06/2010 00:50, Thomas 'PointedEars' Lahn wrote:
>
> | s/_old_/_new_/ | Substitute _new_ for the first
> occurrence of _old_ in the event | line. Any delimiter can be
> used in place of /. The final | delimiter is optional
> if it is the last character of the event | line. The delimiter
> may be quoted in _old_ and _new_ with a single | backslash.
> If& appears in _new_, it is replaced by _old_. A sin‐ | gle
> backslash will quote the&. If _old_ is null, it is set to |
> the last _old_ substituted, or, if no previous history substitu‐ |
> tions took place, the last string in a !?_string_[?] search.

This does not mean that old could not be a regular expression though,
does it? From the example it looks like it can not be, but this is not
explicitly mentioned in the man page (or online, at least on the pages
that I looked at).

> $ ls -l test/ [...] $ !!:0-1 test2/ ls -l test2/ [...] $ ls -l -a
> test/ [...] $ !!:0- test2/ ls -l -a test2/ [...]

I know, I only used it as an example. This not the command I want to
run, the "real" question was: can I have regular expressions in history
substitution using the s modifier or only string literals? From your
examples and my experience I would say string literals only, but if
someone could give a definite answer, that would be great.

Regards,
George
From: Thomas 'PointedEars' Lahn on
George wrote:

> On 03/06/2010 00:50, Thomas 'PointedEars' Lahn wrote:
>> | s/_old_/_new_/ | Substitute _new_ for the first
>> occurrence of _old_ in the event | line. Any delimiter can be
>> used in place of /. The final | delimiter is optional
>> if it is the last character of the event | line. The delimiter
>> may be quoted in _old_ and _new_ with a single | backslash.
>> If& appears in _new_, it is replaced by _old_. A sin‐ | gle
>> backslash will quote the&. If _old_ is null, it is set to |
>> the last _old_ substituted, or, if no previous history substitu‐ |
>> tions took place, the last string in a !?_string_[?] search.
>
> This does not mean that old could not be a regular expression though,
> does it?

I don't know, I can't read it.

> From the example it looks like it can not be, but this is not
> explicitly mentioned in the man page (or online, at least on the pages
> that I looked at).

Why not try a regular expression that bash would support and see if it can
be used? See also ${s/x/y}.


PointedEars