filter error

classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

filter error

William Pursell

I wanted to reverse the lines of text, so I executed
:%!sed -n '1!G;$p;h'

To my dismay, the ! character required an escape.  So
:%!sed -n '1\!G;$p;h'
did what I wanted.

Oddly,
:'<,'>!sed -n "1\!G;$p;h"
doesn't work (the $p fails to happen), but
:'<.'>!sed -n '1\!G;$p;h'
and
:'<.'>!sed -n "1\!G;\$p;h"
do.

It seems that '!' has different escape rules than '$'.  Where
in the manual can I find out what's going on?  How can I change
it?  I think that the ! is being expanded by vim to be a history
replacement, which is behavior that I don't really want.  In short,
is it possible to get "normal" escape rules for '!'?  (By "normal",
I guess I mean "the way I want it" :)
Reply | Threaded
Open this post in threaded view
|

Re: filter error

James Vega-3
On Fri, Feb 24, 2006 at 06:43:17PM +0000, bill wrote:
> Oddly,
> :'<,'>!sed -n "1\!G;$p;h"

Your shell is expanding $p to the empty string.

> doesn't work (the $p fails to happen), but
> :'<.'>!sed -n '1\!G;$p;h'

Your shell isn't doing any variable expansion because the string is in
single quotes.

> and
> :'<.'>!sed -n "1\!G;\$p;h"

You're telling your shell not to perform variable expansion by escaping
the '$'.

> do.
>
> It seems that '!' has different escape rules than '$'.  Where
> in the manual can I find out what's going on?

'man bash' or whatever shell you're using.

> How can I change
> it?  I think that the ! is being expanded by vim to be a history
> replacement, which is behavior that I don't really want.  In short,
> is it possible to get "normal" escape rules for '!'?  (By "normal",
> I guess I mean "the way I want it" :)

To summarize, everything after ":{range}!" is fed to your shell, so all
the issues are with how your shell is interpreting it.  Vim's not
causing any of those changes.

James
--
GPG Key: 1024D/61326D40 2003-09-02 James Vega <[hidden email]>

signature.asc (204 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: filter error

Yakov Lerner
In reply to this post by William Pursell
"bill" <[hidden email]> wrote:

> I wanted to reverse the lines of text, so I executed
> :%!sed -n '1!G;$p;h'
> To my dismay, the ! character required an escape.  So
> :%!sed -n '1\!G;$p;h'
> did what I wanted.
> Oddly,
> :'<,'>!sed -n "1\!G;$p;h"
> doesn't work (the $p fails to happen), but
> :'<.'>!sed -n '1\!G;$p;h'
> and
> :'<.'>!sed -n "1\!G;\$p;h"
> do.

1. Judging by vim documentation, you cannot disable replacement of !
in the :!. But you can comehow control to *what* ! will be expanded
(:he :!, :he 'cpoptions' and search for 'redoing'). But this is not
useful for you, not what you asked.

2. Regarding $, it's not special for vim, but it's special for shell.
The last 3 of your exampkles have to do with '..' vs "..." quotes.
It's shell prerogativem not vim's. For shell, $ is special inside ".."
and not special inside '..'.

As a bottomline, I have 2 tips:
a) It looks like you can't bend the escaping/speciality rules for
such characters, but you can obey them painlessly.
b) you can temporarily change ser to echo to safely see
which chars are replaced and which are not, like:
    :!echo '1\!G;$p;h'

Yakov
--
 
  [hidden email]

--
http://www.fastmail.fm - And now for something completely differentÂ…

Reply | Threaded
Open this post in threaded view
|

Re: filter error

A.J.Mechelynck
In reply to this post by William Pursell
bill wrote:

>
> I wanted to reverse the lines of text, so I executed
> :%!sed -n '1!G;$p;h'
>
> To my dismay, the ! character required an escape.  So
> :%!sed -n '1\!G;$p;h'
> did what I wanted.
>
> Oddly,
> :'<,'>!sed -n "1\!G;$p;h"
> doesn't work (the $p fails to happen), but
> :'<.'>!sed -n '1\!G;$p;h'
> and
> :'<.'>!sed -n "1\!G;\$p;h"
> do.
>
> It seems that '!' has different escape rules than '$'.  Where
> in the manual can I find out what's going on?  How can I change
> it?  I think that the ! is being expanded by vim to be a history
> replacement, which is behavior that I don't really want.  In short,
> is it possible to get "normal" escape rules for '!'?  (By "normal",
> I guess I mean "the way I want it" :)
>
>
>

I'm not 100% sure but it could be due to the different treatment of
single- and double-quoted strings (see ":help expr9" which can be found
by looking at ":help expression-syntax").

Inside a single-quoted string, all characters are represented literally
(none has special meaning) except that in version 7 (but not 6) a double
single quote represents one single quote inside the string.

Inside a single-quoted string, many characters have special meaning and
need to be backslash-escaped if you want to represent them literally.
For instance, $NAME is expanded to the value of the environment variable
$NAME. Thus, $p inside double quotes expands to the value of the
environment variable $p -- or to nothing if it hasn't been defined.

The rules for ! in the arguments to a filter are given under ":help
:range!" which is not very far below ":help filter".


HTH,
Tony.

Reply | Threaded
Open this post in threaded view
|

Re: filter error

Gerald Lai-2
In reply to this post by William Pursell
On Fri, 24 Feb 2006, bill wrote:

>
> I wanted to reverse the lines of text, so I executed
> :%!sed -n '1!G;$p;h'
>
> To my dismay, the ! character required an escape.  So
> :%!sed -n '1\!G;$p;h'
> did what I wanted.
>
> Oddly,
> :'<,'>!sed -n "1\!G;$p;h"
> doesn't work (the $p fails to happen), but
> :'<.'>!sed -n '1\!G;$p;h'
> and
> :'<.'>!sed -n "1\!G;\$p;h"
> do.
>
> It seems that '!' has different escape rules than '$'.  Where
> in the manual can I find out what's going on?  How can I change
> it?  I think that the ! is being expanded by vim to be a history
> replacement, which is behavior that I don't really want.  In short,
> is it possible to get "normal" escape rules for '!'?  (By "normal",
> I guess I mean "the way I want it" :)
>

Would you mind doing it the Vim way? :)

   :g/^/m0

--
Gerald
Reply | Threaded
Open this post in threaded view
|

Re: filter error

William Pursell
In reply to this post by James Vega-3
James Vega wrote:

> On Fri, Feb 24, 2006 at 06:43:17PM +0000, bill wrote:
>
>>and
>>:'<.'>!sed -n "1\!G;\$p;h"
>
>
> You're telling your shell not to perform variable expansion by escaping
> the '$'.
>
>
>>do.
>>
>>It seems that '!' has different escape rules than '$'.  Where
>>in the manual can I find out what's going on?
>
>
> 'man bash' or whatever shell you're using.
>
>

My point is that
sed -n '1!G;$p;h'
works from a shell prompt, but I'm needing to put an extra
escape character for the ! to protect it from vim.  Vim is
expanding the !, while the shell isn't.  The shell respects
single quotes, but vim doesn't seem to be, but only for  '!'
Reply | Threaded
Open this post in threaded view
|

Re: filter error

William Pursell
In reply to this post by Gerald Lai-2
Gerald Lai wrote:

> On Fri, 24 Feb 2006, bill wrote:
>
>>
>> I wanted to reverse the lines of text, so I executed
>> :%!sed -n '1!G;$p;h'
>>
>> To my dismay, the ! character required an escape.  So
>> :%!sed -n '1\!G;$p;h'
>> did what I wanted.
>>
>> Oddly,
>> :'<,'>!sed -n "1\!G;$p;h"
>> doesn't work (the $p fails to happen), but
>> :'<.'>!sed -n '1\!G;$p;h'
>> and
>> :'<.'>!sed -n "1\!G;\$p;h"
>> do.
>>
>> It seems that '!' has different escape rules than '$'.  Where
>> in the manual can I find out what's going on?  How can I change
>> it?  I think that the ! is being expanded by vim to be a history
>> replacement, which is behavior that I don't really want.  In short,
>> is it possible to get "normal" escape rules for '!'?  (By "normal",
>> I guess I mean "the way I want it" :)
>>
>
> Would you mind doing it the Vim way? :)
>
>   :g/^/m0
>
> --
> Gerald
>

I like that!  Except that I don't yet
see an easy way to replace "m0" with
"m'<" to make it useful for a range.
ie
:'<,'>g/^/m'<
doesn't quite work.
Reply | Threaded
Open this post in threaded view
|

Re: filter error

Gerald Lai-2
On Fri, 24 Feb 2006, bill wrote:

> Gerald Lai wrote:
>> On Fri, 24 Feb 2006, bill wrote:
>>
>>>
>>> I wanted to reverse the lines of text, so I executed
>>> :%!sed -n '1!G;$p;h'
[snip]

>> Would you mind doing it the Vim way? :)
>>
>>   :g/^/m0
>>
>> --
>> Gerald
>>
>
> I like that!  Except that I don't yet
> see an easy way to replace "m0" with
> "m'<" to make it useful for a range.
> ie
> :'<,'>g/^/m'<
> doesn't quite work.

You would have to literally type "m" + the line number of '< minus one.
Let's say ":echo line("'<")" produces 7. Then do:

   :'<,'>g/^/m6

There's no way to make it dynamic because '< changes as ":m" is used.
Hope this helps.
--
Gerald
Reply | Threaded
Open this post in threaded view
|

Re: filter error

Gerald Lai-2
On Fri, 24 Feb 2006, Gerald Lai wrote:

> On Fri, 24 Feb 2006, bill wrote:
>
>> Gerald Lai wrote:
>>> On Fri, 24 Feb 2006, bill wrote:
>>>
>>>>
>>>> I wanted to reverse the lines of text, so I executed
>>>> :%!sed -n '1!G;$p;h'
> [snip]
>>> Would you mind doing it the Vim way? :)
>>>
>>>   :g/^/m0
>>>
>>> --
>>> Gerald
>>>
>>
>> I like that!  Except that I don't yet
>> see an easy way to replace "m0" with
>> "m'<" to make it useful for a range.
>> ie
>> :'<,'>g/^/m'<
>> doesn't quite work.
>
> You would have to literally type "m" + the line number of '< minus one.
> Let's say ":echo line("'<")" produces 7. Then do:
>
>  :'<,'>g/^/m6
>
> There's no way to make it dynamic because '< changes as ":m" is used.
> Hope this helps.

Well, we could do: (that means from visual, type ":<C-u>" and..)

   :exe "'<,'>g/^/m".(line("'<")-1)

if we're really that lazy ;)
--
Gerald

Reply | Threaded
Open this post in threaded view
|

Re: filter error

Charles E Campbell Jr
In reply to this post by William Pursell
Quoting bill <[hidden email]>:

> Gerald Lai wrote:
> > Would you mind doing it the Vim way? :)
> >
> >   :g/^/m0
> >
> > --
> > Gerald
> >
>
> I like that!  Except that I don't yet
> see an easy way to replace "m0" with
> "m'<" to make it useful for a range.
> ie
> :'<,'>g/^/m'<
> doesn't quite work.

I use the following map:

nno  <silent> <Leader>fr   :set lz<cr>'aO<esc>ma'':'a+1,.g/^/m 'a<cr>kdd:set
lz!<cr>

by starting at the first line, marking it with ma, moving to the last line,
then \fr .  The core idea is the same as Gerald mentioned.  Making a visual
line mode version should be straightforward, too.

Regards,
Chip Campbell