Operating System - OpenVMS
1831508 Members
3341 Online
110025 Solutions
New Discussion

DCL code to concatenate pairs of lines in a text file

 
Niall Godwin
Advisor

DCL code to concatenate pairs of lines in a text file

I want to write a DCL subroutine to concatenate pairs of lines in a text file; i.e. append line 2 with line 1, line 4 with line 3 and so on. If it's of any help, the second line in each pair begins with the "|" character.

Any suggestions ?

Niall Godwin
12 REPLIES 12
Wim Van den Wyngaert
Honored Contributor

Re: DCL code to concatenate pairs of lines in a text file

Untested :

$ open/read i ifile
$open/write o ofile
$loop:
$ i1=""
$ i2=""
$ read/end=end i i1
$ read/end=end i i2
$ write o "''i1'''i2'"
$ goto loop
$end:
$ if i1 .nes. "" then write o "''i1'''i2'"
$ close i
$ close o

Wim
Wim
Karl Rohwedder
Honored Contributor

Re: DCL code to concatenate pairs of lines in a text file

Niall,

you may simply open the textfile for reading and a new version for writing and scan the whole file, e.g.

$ open/read in file.dat
$ open/write out file.dat
$ loop:
$ read in line1
$ read in line2
$ write out line1,line2
$ goto loop

Be sure to add some error and end-of-file procssing and code for the possibility of an uneven number of lines.

regards Kalle
Art Wiens
Respected Contributor

Re: DCL code to concatenate pairs of lines in a text file

We'll assume that you have some basic knowledge of DCL ... or are you asking someone to write the code?

Basically I would think you want to:
- open a file for reading
- create a loop
- initialize a counter
- read a line of data
- assign it to a symbol
- increment the counter
- read another line
- assign it to a second symbol
- increment the counter
- if the counter is 2
- add the two strings together by assigning to a third symbol
- do what you want with the concatenated string/symbol (write it to a file, display it on the screen etc.
- if no more lines left to read in original file
- close the original file
- do what ever else to terminate the procedure
- send an email, produce an OPCOM message etc.
- else
- reset the counter
- go read some more lines

You can test to see that the second line starts with a | as a "sanity" check in your code.

Depending on how often you need to do this, it might be easier just to do it with a "learned" keyboard sequence in TPU.

Is that what you're asking for?

HTH a bit,
Art
Hein van den Heuvel
Honored Contributor

Re: DCL code to concatenate pairs of lines in a text file

Niall,

What do you want to do if a second line does NOT start with "|"
1) ignore the first line
2) concatenate this lien with the first and wait
3) output the first line and consider the current line a new first?

Here is some sample code for the latter case:

$close/nolog old
$close/nolog new
$open/read old old.txt
$create new.txt
$open/append new new.txt
$partial = 0
$loop:
$read/end=done old record
$if 0.eq.f$loc("|",record)
$then
$ write/sym new part,record
$ partial = 0
$ part = ""
$else
$ if partial
$ then
$ write new part
$ partial = 0
$ else
$ partial = 1
$ endif
$ part = record
$endif
$goto loop
$
$done:
$if partial then write new part
$close old
$close new


Hein van den Heuvel
Honored Contributor

Re: DCL code to concatenate pairs of lines in a text file

Also... how do you want the code to react with missing 'last line'?

If you can trust the input, or want to concatenate anything before a line starting with "|" then a PERL solution becomes really easy:

$ type new.txt ! sample output from prior
een| twee
drie| vier
vijf
zes| zeven


$type old.txt !input for prior and this
een
| twee
drie
| vier
vijf
zes
| zeven
$
$ perl -pe "chomp unless (/^\|/) " old.txt
een| twee
drie| vier
vijfzes| zeven

or into a file:

$ perl -pe "chomp unless (/^\|/) " old.txt > new.txt


Enjoy,
Hein.
Robert Gezelter
Honored Contributor

Re: DCL code to concatenate pairs of lines in a text file

Niall,

My US $ 0.02.

What about the cases where the length of the first line varies? Do you want a constant length first part, or is it just a matter of concatentation, regardless of the length of the first line?

Also, do you want to retain the "|" that precedes the second line?

- Bob Gezelter, http://www.rlgsc.com
Niall Godwin
Advisor

Re: DCL code to concatenate pairs of lines in a text file

Many thanks for your suggestions.
The code below works fine but only when the concatenated string does not exceed the command element limit of 255 chars.
*************************************
$ open/read infile data.psv
$ open/write outfile data.psv;0
$loop:
$ linecount = 0
$ read/end_of_file=done infile line1
$ linecount = linecount + 1
$ read/end_of_file=done infile line2
$ linecount = linecount + 1
$ if linecount .eq. 2
$ then
$ concat = "''line1'" + "''line2'"
$ write outfile concat
$ endif
$ goto loop
$done:
$ close infile
$ close outfile
$ exit
***************************************
Unfortunately the string exceeds 255.
Is there a way around this?
Niall
Volker Halle
Honored Contributor

Re: DCL code to concatenate pairs of lines in a text file

Niall,

use

$ write/symbol outfile concat

See $ HELP WRITE/SYMBOL

Volker.
Thomas Ritter
Respected Contributor

Re: DCL code to concatenate pairs of lines in a text file

Niall, consider using extended DCL. This will allow you to exceed the 255 character limit.

Which version of VMS are you running ?

Here is a recent link on DCL symbol limits.

http://forums1.itrc.hp.com/service/forums/questionanswer.do?threadId=1040077
John Gillings
Honored Contributor

Re: DCL code to concatenate pairs of lines in a text file

Niall,

If this is a one off, then it can be done quickly and simply in EVE. Assuming the "|", enable wildcards, then do a wild find for "\<|" (ie: beginning of line followed by vertical bar). Now LEARN a key sequence FIND NEXT then DEL. Next REPEAT more times than lines in the file and hit your LEARNed key. EXIT.

If it really is just every second line, then a learn sequence DOWN DOWN DEL repeated will also work (after fixing the first pair and setting your cursor to the beginning of the buffer).

If this is to be repeated many times, you can write a TPU script to do it. Example attached. Rename the file to GLUE.TPU and execute with:

$ EDIT/TPU/NODISPLAY/COMMAND=GLUE.TPU yourfile
A crucible of informative mistakes
Niall Godwin
Advisor

Re: DCL code to concatenate pairs of lines in a text file

Thanks to all for your assistance.
Here is the working solution(contatenates 5 lines).

$Concat_Extract: SUBROUTINE
$!
$! DESCRIPTION
$! Concatenates multiple lines of data into one line.
$! Lines of data are read, 3 at a time, and concatenated into one before
$! writing the concatenated line to a new file.
$!
$! INPUTS
$! P1 Extract Filename
$!
$! OUTPUTS
$! New version of Extract, with lines concatenated
$! Exit status set to standard VMS status code
$!
$ original_file = p1
$ concatenated_file = p1 + ";0"
$!
$ call Format_Date " at "
$ msg = pre + "I-CONCAT, Concatenating lines in the extract file: " -
+ P1 + DATE_TIME
$ say msg
$!
$ open/read concatin 'original_file'
$ open/write concatout 'concatenated_file'
$!
$! Start looping through the file, concatenating every 5 lines into one.
$CONCAT_LOOP:
$ linecount = 0
$ read/end_of_file=done concatin line1
$ linecount = linecount + 1
$ read/end_of_file=done concatin line2
$ linecount = linecount + 1
$ read/end_of_file=done concatin line3
$ linecount = linecount + 1
$ read/end_of_file=done concatin line4
$ linecount = linecount + 1
$ read/end_of_file=done concatin line5
$ linecount = linecount + 1
$ if linecount .eq. 5
$ then
$ concat = "''line1'" + "''line2'"
$ concat = concat + "''line3'" + "''line4'" + "''line5'"
$ write/symbol concatout concat
$ endif
$ goto CONCAT_LOOP
$!
$DONE:
$ close concatin
$ close concatout
$!
$! Delete the original file by purging down to one version
$ purge/log statext
$!
$ exit
$!
$ENDSUBROUTINE ! Concat_Extract
Hein van den Heuvel
Honored Contributor

Re: DCL code to concatenate pairs of lines in a text file



For grins, try this:

$perl -i -pe "chomp if ++$i%5" tmp.txt

I believe it does all you want in one line.
If you wanted a space between segments:

$perl -i -pe "s/\n/ / if ++$i%5" tmp.txt

The -i stands for 'in place' and roughly matches:

$ perl -pe "chomp if ++$i%5" tmp.txt;-1 > tmp.txt



Btw.. your question was about pairs of lines, the comments mention 3 lines, the code uses 5 lines.
And your question mentions a recognizable last chunk... that would be my preferred way to code this in case the original files gets a lines off track. Either use it for a new line trigger, or use it to verify you are still in the right spot:

$ perl -pe "if (++$i%5) {s/\n/ /} else {die ""\n5th record does not start with |"" unless /^\|/}" tmp.txt

Cheers,
Hein.