1752407 Members
5733 Online
108788 Solutions
New Discussion юеВ

Re: DCL SCRIPT

 
GNJ
Advisor

DCL SCRIPT

HI
I am learning scripting in Open VMS.
I have a doubt in DCL Scripting. Please help
me in finding this.
I want to restrict the occurance of a
string in a file to minimum - 1
I have a file with contents like shown below
i.e
Hai
Hai
Hai
Hai
More
More
New
New
I want only 1 occurance of this strings
How can I do that using dcl commands
I dont want to change the order.
The output I need is like below.
Hai
More
New

Please help me in doing this

Thanks & Regards
Jayakrishnan G Naik
11 REPLIES 11
Robert Gezelter
Honored Contributor

Re: DCL SCRIPT

Jayakrishnan,

You would have to use the READ statement to read the records of the file into variables and process the entire file. Writing a DCL script in to do this is precisely the same as writing the equivalent program in C/FORTRAN/COBOL, excpt for the syntax.

DCL also does not have arrays, at least directly. You can fake arrays by using symbol substitution.

I would give you a quick example, but I have to run back to a meeting in a few minutes.

- Bob Gezelter, http://www.rlgsc.com
Hein van den Heuvel
Honored Contributor

Re: DCL SCRIPT

>> How can I do that using dcl commands
Do you consider perl a dcl command? I do.
The solution in perl is trivial:

$ perl -ne "print unless $seen{$_}++" old.txt > new.txt


>> I dont want to change the order.

That's a critical observation.
The example data presented is actually sorted.
For that (special?) case you can use
$SORT/NODUPLI old.txt new.txt

Also... the examples suggest that if there are duplicates, then they will be adjacent?
Is that always the case? If so, the DCL becomes easy:

$! ------------- filter.com ----------
$if p2.eqs."" then goto usage
$last = ""
$close/nolog in
$close/nolog out
$open in 'p1
$create 'p2'/log
$open/appen out 'p2
$loop:
$read/end=done in record
$if record .eqs. last then goto loop
$last = record
$write/symbol out record
$goto loop
$
$done:
$close/nolog in
$close/nolog out
$exit
$
$usage:
$write sys$output "ERROR: Must provide input and output file argument"
$exit

Sample

$@filter old.txt new.txt

>> I want only 1 occurance of this strings

May we assume the FIRST occurence needs to be retained?

>> The output I need is like below.

Hmmm... the example input has a SPACE behind one of the 'More' lines.
If there is a space, should it stay, as your output example suggest, or stay?

Cheers,
Hein.
Hein van den Heuvel
Honored Contributor

Re: DCL SCRIPT


>> I am learning scripting in Open VMS.

Ooops, I failed to react to the most important line in the topic. Sorry.

RTFM! notably:
http://h71000.www7.hp.com/doc/731FINAL/6489/6489PRO.HTML
Chapter 13, 14,...

Be sure to check back to your prior questions such as. Carefully read all answers, question everthing (for yourself), use the HELP to exaplain. Follow all links. Read! Try! Try again!

http://forums1.itrc.hp.com/service/forums/questionanswer.do?threadId=1102838


Cheers,
Hein.
GNJ
Advisor

Re: DCL SCRIPT

Hi
I have achieved this with a command,
But some warning messages are coming.
I want to avoid this.
I will give what I have done -below
$ type hai.txt
Hai
Hai
Hai
Hai
New
New
New
END
END
END
TIN
TIN
TIN
TIN
$ pipe type hai.txt|merge/nodup sys$pipe new.txt
%SORT-W-BAD_ORDER, merge input is out of order
%SORT-W-BAD_ORDER, merge input is out of order
$ type new.txt
Hai
New
END
TIN

I got the output I needed but warning message has come. Can we avoid this error
message by doing something?

Regards
Jayakrishnan G Naik
Hein van den Heuvel
Honored Contributor

Re: DCL SCRIPT

>> $ pipe type hai.txt|merge/nodup sys$pipe new.txt


Ouch, booh, hiss, bad Unix thinking!

On VMS most actions operate on identified files.
They do NOT assume STDIN, STDOUT nor STDERR.

Just give SORT, MERGE or whatever the input file. Do NOT force a pipe.

To suppress the error messages you could redirect 'extra' messages to a file for the duration of the command:

$ define/user sys$output errors.log
$ define/user sys$error errors.log
$ merg/nodup/stat tmp.txt new.tmp
$ type errors.log

Hein.




Jan van den Ende
Honored Contributor

Re: DCL SCRIPT

Jayakrishnan,

Welcome to the beautiful world of VMS!

I came onto similar problems several times, where there were dozens of different items, not always all present, not in any orider, and randomly mixed, in thousends of input lines.

Rougly, I used this:

$ count = 0
$ item_zero = ""
$ open/read infile
$ open/write outfile
$loop1:
$ counter = 0
$ read infile rec /end=done
$loop2:
$ counter = counter + 1
$ if counter .gt. count
$ then
$ count = count + 1
$ item_'count = rec
$ goto loop1
$ else
$ if rec .eqs. item_'counter ! already got this one
$ ! mayby increase tally?
$ goto loop1
$ endif
$ goto loop2
$ endif
$ goto loop1
$done:
$ counter = 1
$loop3:
$ if counter .gt. count then goto the_end
$ write outfile item_'counter
$ counter = counter + 1
$ goto loop3
$ close infile
$ close outfile


Ot course, this can be extended by considering only partial records, and tallying, and
But you get the general idea.

hth

Proost.

Have one on me.

jpe
Don't rust yours pelled jacker to fine doll missed aches.
Hein van den Heuvel
Honored Contributor

Re: DCL SCRIPT

"There is nothing so useless as doing efficiently that which should not be done at all"
- David Lloyd George

With that in mind, here is an advanced solution for the stated problem. It needs a helper program for which the macro source is attached.

SORT has a special option call /PROC=ADDRESS
When this is selected, sort will not spit out the data for the selected and sorted records, but only the (6-byte) RFAs for those records pointing back to the input file.

For a sequential file the RFA is in fact a 4 byte VBN for the file block in which the record starts, and a 2 byte byte offset.

So if one were to sort the address file, then the pointers will be back in original order.

But how to get the data itself from RFA's?
I don't think there is a standard tool for that.
DIX or DATATRIEVE might be able to to is (http://oooovms.dyndns.org/dix/).

The attached program will do it.
It takes an input file and a file with rfa's pointing back into that input file to extract data.

The solution then becomes:

$define rfa_input old.txt
$sort/nodup/stat rfa_input tmp.rfa/proces=address
$sort/key=(pos:1,siz:4,unsigned,binary)/key=(pos:5,siz:2,unsigned,binary) tmp.rfa rfa_select.rfa
$define rfa_output tt:
$run rfa ! attached MACRO program

Back to real work...
Hein.







Brad McCusker
Respected Contributor

Re: DCL SCRIPT

>There is nothing so useless as doing
>efficiently that which should not be done
>at all"
>- David Lloyd George

Wow Hein, you sure can say that again! ;^) (Especially when it appears that what he wants to do can be done in one simple line of DCL. ;^) )

The base noter never responded to Hein's original questions, in particular this one:

>Also... the examples suggest that if there >
>are duplicates, then they will be adjacent?
>Is that always the case?

Assuming duplicates are adjacent, then the solution should be as simple as:

$merge/nodup/nocheck_seq file.in file.out

However, I suspect I've found a bug in SORT. That command only works correctly (my interpretation of correct) if you use HYPERSORT. It should be no big deal to use HYPERSORT, simply define the following logical:

$define sortshr sys$library:hypersort.exe


In the capture below, I demonstrate the command with the default sort and then again with HYPERSORT. For more information on HYPERSORT, see The HP OpenVMS Users Manual, Chapter 9. HYPERSORT is discussed in 9.1. Hein alreaady provided the pointer, but, here it is again: http://h71000.www7.hp.com/doc/731FINAL/6489/6489pro_contents.html


$ty file.txt
Hai
Hai
Hai
Hai
New
New
New
END
END
END
TIN
TIN
TIN
TIN
$merge/nodup/nocheck_seq file.txt file.out
$ty file.out
Hai
Hai
Hai
Hai
New
New
New
END
END
END
TIN
TIN
TIN
TIN
$! Whoops - it didn't work!?
$! Let's try the High Performance Sort
$sho log sortshr
%SHOW-S-NOTRAN, no translation for logical name SORTSHR
$define sortshr sys$library:hypersort.exe
$merge/nodup/nocheck_seq file.txt file.out
$ty file.out
Hai
New
END
TIN
$

Brad McCusker
Software Concepts International
Hein van den Heuvel
Honored Contributor

Re: DCL SCRIPT

Hi Brad

>> Especially when it appears that what he wants to do can be done in one simple line of DCL. ;^)

I tried that line, but it did not work even for the simple case.
Dunno why I did not challenge that as a bug.

Anyway, it certainly would not work for the most general case where the duplicates are not adjacent.

I did not think about using Hypersort though!
Excellent workaround!

btw... directing hypersort output to tt: does not work. The carriage return attributes are not respected. Need to go to a file and then type as Brad shows.


Hein.