Link to home
Start Free TrialLog in
Avatar of dizzard
dizzard

asked on

Writing a script to edit a file in vi

I'm trying to write a script that will perform a substitution and an insert in vi.
here's what I have so far.

vi [filename]
1,$s/&/,/g

I was told to put an escape character in, but I'm not sure what that would be

I would appreciate any help I could get

Thank you.
Avatar of RobWMartin
RobWMartin

You mean a line insert?  Like find all &'s replace with , then break the line?

Rob
Avatar of dizzard

ASKER

yes exactly.  If it matters I also have to do a second replace. Where I have to replace all the tabs with nothing.

Thanks again!
Ok.  Trying to write a script?  Like in open vi with a file and pipe the "script" in through stdin?  You're wanting to do this for more than one file (i.e. more than a one time use)? Do you have to use vi?  Do you have access to vim?

Sorry for all the questions.

Rob
D@mn, I keep hitting the esc key and having to retype this.  Thank you dizzard, for getting me in vi mode:)

Anyhow, to try something other than answering questions:

in vi

:%s/&/,^M/g

To get the ^M, hold down ctrl and press V, then press return key.  ^V sez escape the next keypress.  Do the same thing with tabs, hitting the tab key instead of the return key.  It will look like this:

:%s/^I//g

Now to pump this into vi automatically:

echo -e ":%s/&/,^V^M/g\n:wq" | vi file

The ^V^M sequence results from three ctrl-V 's and a return.  My shell recognizes ctrl-V as an escape.  If yours doesn't we'll have to explore further.

Rob
Ooops.  Forgot to add the tabs part:

echo -e ":%s/&/,^V^M/g\n:%s/^V^I//g\n:wg" | vi file

:P
Avatar of dizzard

ASKER

Rob,  When I press the tab key I do not get the "I" instead I get blank space like it inserting a tab.  The first search and replace works great though.

Thanks for your patience.
Avatar of dizzard

ASKER

Rob,  When I press the tab key I do not get the "I" instead I get blank space like it inserting a tab.  The first search and replace works great though.

Thanks for your patience.
Dear Dizzard,

Let me first mention what I understood about your question.

1. You want to work in vi
2. You need to replace all '&' by newline
3. You need to replace all tabs by space or NULL.

if this is correct just take this as general rule for seraching and replacing any sequence of characters by other sequence of characters in vi.

There are two ways to do it one is as identified by Rob but I will write it more clearly.

A:
     step 1 -> open the file in vi
     step 2 -> type the following sequence
                    :1,$s/&/^M/g
              expalination of this sequence
              1,$  => search from first line to last line ( 1 for first, $ for last)
              s/ => search instuction string specified in first to '/' characters
             /&/ => the string in first two / is string to be replaced
            /^M/ => the string in next two / is new string
             g      => globally in the file.

           How to generate ^M i.e. newline character.
               For new line press ctrl key and while pressed
               press 'v' key & then 'm' key.
               i.e. ctrl v m
           How to generate ^I i.e. tab character.
                   press  ctrl v Tab
               or press ctrl v i
          your required command will look like
              :1,$s/^I/ /g
           or
              :1,$s/        / /g
              this will replace tab by single space
              :1,$s/^I//g
           or
              :1,$s/       //g
              this will replace tab by null character.

B: This can also be done using other sequence in vi
    step 1 -> open the file in vi
    step 2 -> type the following sequence
                   :g/&/s//^M/g
                   This will search all & in file and replace them by newline ^M
                   first g indicated global in line and second g indicates
                   all the lines.
                   here you have flexibility of handling the search replace
                   within line or across the file.    



Hope this satisfies you.          
Dinesh,

We got it covered inside vi.  But I think Dizzard wants to run it as a script.  I.e. feed vi the commands and a file to work on.  Dizzard has me stumped on getting a ^I from the shell prompt into vi.

Sorry, Dizzard,  I haven't had a chance to look into again.

Rob
you cannot script with vi, but awk or sed or perl; perl is the simplest solution (just a few bytes;-)
Avatar of dizzard

ASKER

How would you do substitutions like these with awk or sed?  Really it does work in vi, except I can't find what the "special" character is for a tab on my system.

there could be a dozent of reasons ...
Assuming that you tried RobWMartin's echo -e example, I'm not wondering if it doesn't work (even it might do), 'cause it depends on the shell, and the used echo command, and the settings of your tty (and probably some more like xmodmap if you're running under X, etc. etc.)

As I said befor, vi is a program for interactive use: vi - view inteactive
for performing such task there are numerous programs: awk, sed, tr, perl, just to name a few.
Best is to go with these, and not struggling with windmills ...
Instead of discussing all these let us understand dizzard's requirement.

Is he interested in how to search and replace a pattern in file(s) or his interest is "how to do this using vi"

If the interest is in writting shell script, and tool is not the concern, then there are many  ways as identified by ahoffmann. But if the requirement is using vi as he has identified in his original question then the solution is unique as I mentioned earlier.
Dizzard,

Ok.  I've had a chance to try something else:

echo -e ":%s/&/,^V^M/g\n:%s/\t//g\n:wg" | vi file

This worked on my system.  The difference is the ^V^I is simply replaced with \t.  Echo subs in the real tab character, and vi accepts it.  I wouldn't try the same thing with the ^V^M (i.e. subbing \n), because vi would read that as premature end of command.  Note: the solution will delete all the tabs.  If you want to replace them (all) with a single space then use s/\t\t*/ /g instead.

Hope this does it!
Rob
> This worked on my system.
That's possible.
But as I said before, forget about piping commands into vi, you have to beat a lot of dragons. Just an example, simply change
  stty oxtabs
or vice versa
  stty -oxtabs
and the printed examples above may no longer work as described
Dude, you're talking terminals, I'm talking raw ascii.  Output from echo -e doesn't get translated for tty when it's moving through the pipe.  vi may try, but it is smart enough to recognize that the other end of the pipe is not a tty.  Besides if it satisfies Dizzard, then who cares.

Actually, I agree with you on the ^V^V^V^I being sensitive to tty settings.

Rob
which echo? (shell, BSD-style, etc.)
Have you really testied all variants? (dude:  I know that I'm very picky ;-)
Ok, now you're talking shells.  I mentioned in my fourth comment, that there may be shell dependencies.  I totally agree with you, if this were a general purpose effort, with publication in mind.  However, in that case, I certainly wouldn't be wasting time with a vi "script."  If it works in Dizzard's shell, then we're done.  If not, like I've said before, we can pursue something else.

BTW: I don't think you're picky.  It's just obvious that you've got alot of programming/scripting experience under your belt; probably for large, heterogenous installation where thinking it through is vital.  I have to think that way, too, most of the time.  However, I love these little "projects" where you can just glue things together, run it a few times, and then forget about it.  In such cases, I don't worry about the implications of portability.

Later, Dude :)
Rob

nice comment Rob ;-)
(tty, shell, echo, it all plays together, sometimes, somehow)
BTW, now you're talking ...

probably we should wait for dizzards comments now, instead of chatting
Avatar of dizzard

ASKER

The \t worked perfectly!!!!!!!

Thanks Rob!

Thanks everyone for being so helpful and patient.  I really appreciate all the help.



You're very welcome.  That's why we're here:)
try this

#gres
THIS=$1
WITH_THAT=$2
shift
shift

for i in $@
do
#echo "working on $i"
ed - $i <<END
1,\$s/${THIS}/${WITH_THAT}/g
w
q
END
done
~

# this will replace DOG with CAT in ALL files (matching arg3)
ASKER CERTIFIED SOLUTION
Avatar of RobWMartin
RobWMartin

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of dizzard

ASKER

Rob's comments helped and solved my question.