wrapper script design for gnu ed text editor i/o


 
Thread Tools Search this Thread
Top Forums Shell Programming and Scripting wrapper script design for gnu ed text editor i/o
# 1  
Old 10-12-2012
wrapper script design for gnu ed text editor i/o

Hi. I'm having trouble writing a wrapper script for the command line text editor gnu ed.

I want to be able to run the following algorithm on ed:

1. Display, on stdout, a command which I intend to feed into ed (before I actually feed it to ed).
2. Actually feed the command into ed's stdin.
3. Wait until ed finishes displaying whatever stderr and stdout it must, redirecting all (stderr and stdout) to stdout.
4. End if the command is q or Q.
5. Otherwise, go back to step 1.

I want to achieve this, in order to be able to automate ed (or any other command-line utility for that matter) through bash scripts, WHILE displaying all i/o interaction (this is important).

Anyway, my first try was to use the following shell script

display_and_feed.sh
:
Code:
#!/bin/bash

while read LINE ; do
        echo ${LINE} 1>&2
        echo ${LINE}
done

as follows

Code:
$ printf ",p\nh\na\nhello\nworld\nhow are you\n.\n,p\nh\nh\nQ\n" | ./display_and_feed.sh | ed

the problem being, that I get this messy, disordered output (which consists of a mix of stderr and stdout, by the way):
Code:
,p
h
?
a
Invalid address
hello
world
how are you
.
,p
h             <-- command 'h' shows before output of ',p'
hello
h
world
how are you
Invalid address
Invalid address
Q

...so I'm thinking, "maybe an ugly time delay will do...", so then I write a new script:

display_and_feed_with_delay.sh :
Code:
#!/bin/bash

while read LINE ; do
        echo ${LINE} 1>&2
        sleep 0.5
        echo ${LINE}
        sleep 0.5
done

...I run:
Code:
$ printf ",p\nh\na\nhello\nworld\nhow are you\n.\n,p\nh\nh\nQ\n" | ./display_and_feed_with_delay.sh | ed

And sure enough, the (SLOW) script, returns the orderly output:
Code:
,p
?
h
Invalid address
a
hello
world
how are you
.
,p
hello
world
how are you
h
Invalid address
h
Invalid address
Q

So I unsuspectingly cheer and celebrate, but when I try to store it all neatly in a file, I get:
Code:
$ { printf ",p\nh\na\nhello\nworld\nhow are you\n.\n,p\nh\nh\nQ\n" | ./display_and_feed_with_delay.sh | ed ; } >file 2>&1
$ cat file
,p
?
h
Invalid address
a
hello
world
how are you
.
,p
h                   <-- where did the output of ',p' go?
Invalid address
h
Invalid address
Q
hello             <-- Oh... THERE it is...
world
how are you

Apparently, stderr gets redirected to file before stdout does. I am puzzled. Why does this happen??

By the way, this also happens when I try to use a pipe instead of redirecting to a file:
Code:
$ printf ",p\nh\na\nhello\nworld\nhow are you\n.\n,p\nh\nh\nQ\n" |  ./display_and_feed_with_delay.sh | ed |& cat
,p
?
h
Invalid address
a
hello
world
how are you
.
,p
h                   <-- ...once more...
Invalid address
h
Invalid address
Q
hello             <-- ...stdout shows only after ed ends.
world
how are you

Is this an exclusive ed behavior, or do all programs first pipe their stderr and then their stdout? Is there a way to merge (interwine, in the correct order) stderr and stdout, for ed, in a case like this?

I mean, this behavior is kinda funny, because, when I run stuff like
Code:
$ { echo "1" ; echo "2" 1>&2 ; echo "3" ; } |& cat

I get
Code:
1
2
3

Not
Code:
2
1
3

By the way: it would be awesome if there was a way to tell when ed is expecting new input, so that I can signal some script, which sends input into ed, when the moment is right, to feed ed more commands, instead of using some ugly sleep 0.5 time delay. Is there any way to do this?

Last edited by vomv1988; 10-12-2012 at 10:36 AM..
# 2  
Old 10-12-2012
There are a number of wrong presumptions in your post about how some Unix-facilities work. I will try to address them one by one. Bear with me, sometimes the relation of explanation and problem will not immediately become clear. It will (should) make sense in the end.

You have to picture a Unix process like a garden hose. You put something in on top and it comes out at the bottom. If you connect two such processes with a pipeline symbol you stick two of these garden hoses together, so that the outcome of one goes directly into the other.

Now the picture of the garden hose is simple, but yet a bit misleading: first off, because processes change the data stream they are working on: you put lots of blue water in on top and get a small amount of red water out on bottom (or vice versa). But the more important shortcoming of the picture is that the garden hose is Y-shaped: it has two outputs, STDOUT and STDERR (and even more outputs if you defined them, but these two are there per default).

Notice that there is a strict difference between the outlet of a garden hose and the place it is directed at. You can catch what comes out of the hose by either this bucket or the other (or, see above, even the intake of another garden hose), but there is still a difference between the destination a hoses ending is pointed at and the destination itself.

Coming back to your script from this rather theoretical explanation: a command like "2>&1" means: "direct what comes out of stderr (one hose ending) to where the stdout (the other hose ending) is already pointing at". This does in no way imply that these two streams are now somehow "merged". They are not. They are just pointing to the same bucket, but are still two different hose endpieces. If you first redirect stderr to point to the same bucket (file or pipeline) as stdout and then redirect stdout to point to another bucket stderr will not be affected in any way - two different streams.

Now for another misconception directly related to your last point with the redirected "echo"s: in fact it is in no way guaranteed to get any particular succession if different streams are involved. If you write:

Code:
(echo a; echo b) | cat

you are guaranteed that "a" is displayed before "b". If you have "c" and then "d" coming out of stderr and you merge these two streams in one destination you are also guaranteed that "c" shows up before "d", but there is no such guarantee that "c" or "d" will show up in any particular position relatively to "a" or "b". it could be "a-b-c-d" or "c-d-a-b" or even "c-a-d-b" or "a-c-b-d" - all these variations would be valid ouputs for the following code:

Code:
(echo a; echo b; echo c >&2; echo d >&2) 2>&1 | cat

The reason is that stderr and stdout are radically different even if they look just like two of the same kind: one of them is buffered, the other one unbuffered. That means that repeated calls to output something are stored and then handled in one big rush versus processing each request as soon as it comes.


Another thing you seem to miss is a rather small issue: "sleep" can only handle integers. "sleep 0.5" might work on some system if this system has extended the standard but will definitely fail on most. If you want to "sleep for less than a second" i suggest you search this board for the "nodoff" utility Perderabo has programmed once.

I hope this helps.

bakunin
This User Gave Thanks to bakunin For This Post:
# 3  
Old 10-12-2012
thanks, bakunin

This bit...
Quote:
Originally Posted by bakunin
The reason is that stderr and stdout are radically different even if they look just like two of the same kind: one of them is buffered, the other one unbuffered. That means that repeated calls to output something are stored and then handled in one big rush versus processing each request as soon as it comes.
...inspired me to search for "make stdout unbuffered bash" in google, which led me to a stack overflow thread, which in turn referred me to the expect command, which pretty much solves my original problem.

Thanks for the buffering details of stdin and stdout, bakunin, I appreciate it.

Last edited by vomv1988; 10-12-2012 at 04:15 PM..
Login or Register to Ask a Question

Previous Thread | Next Thread

9 More Discussions You Might Find Interesting

1. Shell Programming and Scripting

Help needed on wrapper script

Hi Gurus, I need to build a wrapper script which will be passing the loading date and the data file name (provides option to the user to load a single data file or load all the data files) to the actual loader data_load.ksh to load in the database. 1. I want to execute the loader script... (6 Replies)
Discussion started by: express14
6 Replies

2. Shell Programming and Scripting

Command line: add text wrapper around words

I am trying to build a sinkhole for BIND. I created a master zone file for malicious domains and created a separate conf file, but I am stuck. I have a list of known bd domains that is updated nightly. The file simply contains the list of domains, one on each line: Bad.com Bad2.com... (4 Replies)
Discussion started by: uuallan
4 Replies

3. Shell Programming and Scripting

problem with the my wrapper script

Hi friends, i am working in ksh88. i am running the follwing wapper script in background to run two jobs parallely((eg nohup wrapper.ksh &):: wrapper.ksh ######################## #!/bin/ksh nohup ./pii_insert.ksh /nsing83/p2/test & nohup ./pii_update.ksh... (1 Reply)
Discussion started by: neelmani
1 Replies

4. UNIX for Advanced & Expert Users

Pass parameter to the main script from wrapper script

Hi, I am writing a wrapper script(wrap_script.sh) to one of the main scripts (main_script.sh) The main script is executed as following: ./main_script.sh <LIST> <STARTDATE> <ENDDATE> looks for a parameter which is a LIST(consists of different list names that need to be processed), START/END... (0 Replies)
Discussion started by: stunnerz_84
0 Replies

5. Shell Programming and Scripting

Count script wrapper help

I have this a code that I got help with for another task. I since tried to modify it to work on this task. I need someones expertise to modify it slightly and I am not sure where to start or yet fully understand the logic. I am trying to get a script to read my m-names.txt which has lots... (19 Replies)
Discussion started by: richsark
19 Replies

6. Shell Programming and Scripting

wrapper script in perl

Hi, I am in need of way to facilitate this senerio in a perl script. I have CLI ( command line interface) which I run like so: kip-tepltist -u Xxx -p Xxx Which produces tones of names from each template it found: 194Iselin-NJ 33-IDFLB-North-611-Woodward-8600 ... (5 Replies)
Discussion started by: richsark
5 Replies

7. Shell Programming and Scripting

Help with a wrapper script not working

Hello, I have the below wrapper script: #!/usr/bin/perl -w if ($^O eq 'MSWin32' ) { $subnet = 'c:\path\to\subnet.txt'; } else { $subnet = '/opt/qip/wrapper-del-sub'; } open FH1, 'jj-deleted-subnets.txt' or die "Can't open 'jj-deleted-subnets.txt' ... (0 Replies)
Discussion started by: richsark
0 Replies

8. UNIX for Dummies Questions & Answers

Pasting text in VI editor from a different editor

Hi, I knw its a silly question, but am a newbie to 'vi' editor. I'm forced to use this, hence kindly help me with this question. How can i paste a chunk 'copied from' a different editor(gedit) in 'vi editor'? As i see, p & P options does work only within 'vi'. (10 Replies)
Discussion started by: harishmitty
10 Replies

9. UNIX for Dummies Questions & Answers

What is a wrapper script

I tried searching the forum ,,but couldn't locate ..Can anyone give me a link or some information about wrapper script. (1 Reply)
Discussion started by: thana
1 Replies
Login or Register to Ask a Question