HPE Community read-only access December 15, 2018
This is a maintenance upgrade. You will be able to read articles and posts, but not post or reply.
Hours:
Dec 15, 4:00 am to 10:00 am UTC
Dec 14, 10:00 pm CST to Dec 15, 4:00 am CST
Dec 14, 8:00 pm PST to Dec 15, 2:00 am PST
Operating System - OpenVMS
cancel
Showing results for 
Search instead for 
Did you mean: 

Can you do a F$EXTRACT on a PIPE output

 
Niall76
Frequent Advisor

Can you do a F$EXTRACT on a PIPE output

Hi,

I'm trying to extract certain sections of lines in a report. First I find the lines I want and then I attempt to extract the section of that line I want. I would like to be able to do this without creating any temporary files, but just using the sys$input. Here is my attempt:

pipe typ sample.rep | search/match=and SYS$INPUT 8148, 5.00 | READ/END_OF_FILE=exit SYS$inPUT record F$EXTRACT(12,10,RECORD)

It works up to the second pipe, I'm just not able to 'extract' the section of the line I want out of the terminal output. Can anyone help me out please?

Thanks,
Niall
12 REPLIES
Joseph Huber_1
Honored Contributor

Re: Can you do a F$EXTRACT on a PIPE output

Correct the second part to read:

(READ SYS$PIPE record ; record=F$EXTRACT(12,10,RECORD) ; define/job record &record)

A READ in a pipe can have no error/end label (where do You think the label "exit" is ?)
If You want to have read error handling, and/or read of more than one line, then pipe into a DCL command-file, which does a loop on READ SYS$PIPE: Your search most probably DOES output more than one line to the pipe !
The above SEARCH+READ only gets the first line, not what You want. use SEARCH/WINDOW=1 .
http://www.mpp.mpg.de/~huber
Hein van den Heuvel
Honored Contributor

Re: Can you do a F$EXTRACT on a PIPE output


Niall, what are you going to do with the result? Stick it in a logical?
And then what? What problem are you really trying to solve, and is convoluted DCL really the best way to go about that?

Here is some DCL that works for me.
I dropped the first pipe segment as search is perfectly able to read a file itself. It needs no help from type does it?

$ pipe typ tmp.tmp | search/match=and SYS$INPUT 8148, 5.00 | (read sys$pipe x ; x=f$extr(12,10,x) ; def/job x &x)
$ show log x

Using PERL this looks like:

$ perl -lne "print substr($_,12,10) if /8148/ && /5.00/" tmp.tmp

Or AWK if you prefer...

$ gawk "/8148/ && /5.00/ { print substr($_,13,10) }" tmp.tmp

If more string processing needs to take place, or more complex matching algorithms are needed (general, not specific values and/or more rigorous placement/anchors for the match strings), then a perl or awk solution with REGULAR EXPRESSIONS quickly becomes more advantageous.

For example:

$ perl -ne "print $1 if /^\s*8148.*?5.00(.{10})/" tmp.tmp


That REGEXPR says look for a like starting with (^) optional whitespace (\s*) followed by 8184 followed by any number of anything (.*?) up to 5.00, then save (()) 10 times anything (.{10}) into register $1

Often one of two of those number are variables which need to be picked up, and the string of 10 is really just a single word.
The line might then become

$perl -ne "print qq($2 $1) if /^\s*8148\s+([0-9.]+)\s*(\w+)/" tmp.tmp

^ = Begin of line
\s = whitespace
\s+ = 1 whitespace or more
\s* = any number of whitespace
[0-9.] any character in the range 0 - 9 or a period
[0-9.]+ = series of one or more of those
\w = a word character
\w+ = a word
qq() = double quoted string doing substitutions (avoid quote fights with DCL)

hth,
Hein





Joseph Huber_1
Honored Contributor

Re: Can you do a F$EXTRACT on a PIPE output

Example:

$ pipe typ sample.rep | search/match=and SYS$INPUT 8148, 5.00 | @logical_from_pipe RECORD

$ record=f$trnlnm("RECORD","LNM$GROUP")
$ this = F$EXTRACT(12,10,RECORD)

Where logical_from_pipe.com is
http://www.mpp.mpg.de/~huber/util/com/logical_from_pipe.com

A version reading more than one line from pipe into logicals was posted by R.Boyd here (or at www.openvms.org ?), You can find my version on the above web location as logicals_from_pipe.com .
http://www.mpp.mpg.de/~huber
Hein van den Heuvel
Honored Contributor

Re: Can you do a F$EXTRACT on a PIPE output

Actually... I did not drop the 'type' command in the example I happende to cut & paste.

Correction:

$ pipe search/match=and tmp.tmp 148, 5.00 | (read sys$pipe x ; x=f$extr(12,10,x) ; def/job x &x)


Using perl and defining a logical(*)

$perl -ne "$ENV{x} = substr($_,12,10) if /8148/ && /5.00/" tmp.tmp
$ show log x


(*) For the latter, see also
http://forums13.itrc.hp.com/service/forums/questionanswer.do?threadId=1408424


Hein


Niall76
Frequent Advisor

Re: Can you do a F$EXTRACT on a PIPE output

thanks guys for your quick responses. You have probably guessed that I don't really know what I'm doing and the fact that I should have mentioned I wanted it to loop. When I do the search this way I get:

pipe search/match=and sample.txt 8148, 5.00
AAAA 0 0 0 5.00 8148 AA1234 1426 2216 ...
AAAA 0 0 0 5.00 8148 AA12345 3287 2216 ...
AAAA 0 0 0 5.00 8148 AA756 703 2216 ...

With the new and improved pipe:
$ pipe search/match=and sample.txt 8148, 5.00 | (read sys$pipe info ; x=f$extr(37,4,info) ; y=f$extr(41,10,info) ; write sys$output x, y)
8148 AA1234

But what I want is:
8148 AA1234
8148 AA12345
8148 AA756

I'm sorry, but from your examples and links I can't figure out how to do it.

Thanks,
Niall
Graham Burley
Frequent Advisor

Re: Can you do a F$EXTRACT on a PIPE output

Sounds like you really need a port of the unix cut utility to complete your pipe-fest.

It's possible that SORT can do it for you, depending on what the input file is really like (space aligned, etc). Making some assumptions about what you posted, an example:

$ type a.a
0000000001111111111222222222233333333334444444444555555555566666666667
1234567890123456789012345678901234567890123456789012345678901234567890
AAAA 0 0 0 5.00 8148 AA1234 1426 2216 ...
AAAA 0 0 0 5.00 8148 AA12345 3287 2216 ...
AAAA 0 0 0 5.00 8148 AA756 703 2216 ...

$ type a.srt
/field=(name=f1,pos:33,siz:4)
/field=(name=f2,pos:38,siz:4)
/field=(name=f3,pos:43,siz:9)
/condition=(name=c1,test=((f1 eq "5.00") and (f2 eq "8148")))
/include=(condition=c1)
/data=f2
/data=f3

$ sort a.a /spec=a.srt sys$output
8148 AA756
8148 AA1234
8148 AA12345
RBrown_1
Trusted Contributor

Re: Can you do a F$EXTRACT on a PIPE output

If you want to have a loop, then you need to put the DCL that does the READ ... WRITE in a command file and code a loop. Then you could PIPE SEARCH/MATCH=AND SAMPLE.REP 8148,5.00 | @FILTER for example.

hth
RBrown_1
Trusted Contributor

Re: Can you do a F$EXTRACT on a PIPE output


I see that Graham and I got the same time stamp! :-)
Graham Burley
Frequent Advisor

Re: Can you do a F$EXTRACT on a PIPE output

And in posting that example all spacing was lost, hopefully the point wasn't.
Hein van den Heuvel
Honored Contributor

Re: Can you do a F$EXTRACT on a PIPE output

>> I should have mentioned I wanted it to loop.

Then you can not just use a 'one liner'.
You'll need a helper command file, or a better programming language.


For example, with tmp.com being
-----
$open/read pipe sys$pipe
$loop:
$read/end=done pipe rec
$write sys$output f$ext(37,17,rec)
$goto loop
$done:
----------
$ pipe search/match=and tmp.tmp 8148, 5.00 | @tmp

I suppose you could generate the helper on the fly, and delete. I sometimes 'embed' it in the main procedure, calling itself with a label to jump to.

------ $!test.com
$if p1.nes."" then goto 'p1
$pipe ... | @'f$env("procedure") print_it
:
$exit
$print_it:
$open/read ...
$loop:
$ ...
$goto loop
--------

But if you go that route, why not have the DCL script do the loop/search?
(Possible answer... too much data to process efficiently by DCL )

-----
$close/nolog tmp
$open/read tmp tmp.tmp
$loop:
$read/end=done tmp rec
$if f$len(rec).eq.f$loc("8148",rec) .or. f$len(rec).eq.f$loc("5.0",rec) then goto loop
$write sys$output f$ext(37,17,rec)
$goto loop
$done:
$close tmp
-------------

Or just using perl:

$ perl -lne "print $1 if /5.00\s+(8148.{10})/" tmp.tmp


But surely that little table is not the end goal.
And possible those 5.0 and 8148 are not really string constants.
So what are the prior and next steps?
What is the real problem you are trying to solve?

pipe's may or might not be useful in solving the real problem.
Perl or awk may or might not be more useful

Hein
John Gillings
Honored Contributor

Re: Can you do a F$EXTRACT on a PIPE output

Niall,

PIPE is great, but can often get too convoluted to be worthwhile. Pipe stages through command procedures to write more complex code.

You'd think that doing everything in memory would outperform writing to disk, but counterintuitively, PIPE is usually MUCH slower (but you avoid generating temp files and the need to clean up). For complex text processing a Perl script will usually be simpler and faster.

Regarding /ERROR or dealing with errors in general. Don't forget there are "&&" (if success) and "||" (if error) separators. Unfortunately you need to explicitly return status, if your mainline needs to know the result.

Examples:

$ PIPE (SHOW JUNK && SHOW TIME || EXIT &$STATUS.OR.%X10000000)
$ SHOW SYM $STATUS
$STATUS == "%X10038060"

or

$ PIPE (SHOW JUNK || EXIT &$STATUS.OR.%X10000000 && SHOW TIME ; SHOW PROCESS ; SHOW SYSTEM)

[.OR. with STS$M_INHIB_MSG to prevent duplicate error message when exiting the pipe.]
A crucible of informative mistakes
Niall76
Frequent Advisor

Re: Can you do a F$EXTRACT on a PIPE output

Thanks all for your responses.