Print and write in one line? - file-io

Is it possible to print something in the screen and, at the same time, that what is being printed is also written in a file?
Right now, I have something like this:
print *, root1, root2
open(unit=10,file='result.txt'
write(10,*), root1, root2
close(10)
I feel like I'm wasting lines and making the code longer that it should be. I actually want to print/write much more lines that these, so that's why I'm looking for a cleaner way to do it.

Writing to standard output and writing to file are two different things, so you will always need separate instructions. But you don't have to open and close the file for every line you write.
Honestly, I don't think it's that much more of an effort:
open(unit=10, file='result.txt', status='replace', form='formatted')
....
write( *, *) "Here comes the data"
write(10, *) "Here comes the data"
....
write( *, *) root1, root2
write(10, *) root1, root2
....
close(10)
this is only one line more than what you would have to do anyway per write statement.
If you really think that you have too many write statements in your code, here are a few ideas that you might try:
If you are running on a Linux or Unix system (including MacOS), you can write a program that only writes to standard out, and pipe the output into a file, like this:
$ ./my_program | tee result.txt
This will both output the data to the screen, and write it into the file result.txt
Or you could write the output to a file in the program, and 'follow' the file externally:
$ ./my_program &
$ tail -f result.txt
I just had another idea: If you really often have the issue that you need to write data to both the screen and the file, you can place that into a subroutine:
program my_program
implicit none
real :: root1, root2, root3
....
open(10, 'result.txt', status='replace', form='formatted')
....
call write_output((/ root1, root2 /))
....
call write_output((/ root1, root2, root3 /))
....
call write_output((/ root1, root2 /))
....
close(10)
....
contains
subroutine write_output(a)
real, dimension(:), intent(in) :: a
write( *, *) a
write(10, *) a
end subroutine write_output
end program my_program
I am passing the values to be written here as an array because that gives you more flexibility in the number of variables that you might want to print. On the other hand, you can only use this subroutine to write real values, for others (integer, character, etc) or combinations thereof you'd need to still have two write statements, or write other specific 'write to both' routines.

Related

non-advancing WRITE...but not intentionally?

I have a brief snippet of code from a Fortran 95 program that should, in theory, spit out my results into some text files. It would be convenient, for readability if nothing else, for the data to be written in columns (so, one column for variable X, one for Y, etc.). In the first set of WRITE commands below (i.e., those associated with the first OPEN command), the idea is to have a text identifier for the user to read, followed by a numeric value. In the second write command, I just dump out four columns of data, each specific to a given variable.
open(unit=10,file='outs_sum.txt',status='replace')
do i=1,1
write(10,'(a12,f5.4)') 'Min. sigma: ',sigma_low
end do
do i=1,1
write(10,'(a12,f5.4)') 'Max. sigma: ',sigma_high
end do
write(10,'(a11,f5.4)') 'Sigma inc: ',0.005
write(10,*) '# of sigmas: ',ii
write(10,'(a9,f5.1)') 'Min. DL: ',dl_low
write(10,'(a9,f5.1)') 'Max. DL: ',dl_high
write(10,*) 'DL inc: ',1
write(10,*) '# of DLs: ',i
write(10,*) 'Total rows: ',(i*ii)
close(unit=10)
open(unit=10,file='outs.txt',status='replace')
do i=1,dls
do ii=1,sigmas
write(10,*) gtow_out(i,ii),ctsig_out(i,ii),sigout(i,ii),dlout(i,ii)
end do
end do
close(unit=10)
However, what happens on the output side is this: the latter WRITE does exactly what I'd expect and spits out the data in column form...but the former insists on writing everything to the same row. At least when I open things in Notepad. If I use GVIM, it looks as it should.
Why does the first set of WRITE commands write to the same row, and how can I force it to insert a line break after each command instead? Alternatively, is Notepad just showing me something that isn't really there?

How to store a result to a variable in HP OpenVMS DCL?

I want to save the output of a program to a variable.
I use the following approach ,but fail.
$ PIPE RUN TEST | DEFINE/JOB VALUE #SYS$PIPE
$ x = f$logical("VALUE")
I got an error:%DCL-W-MAXPARM, too many parameters - reenter command with fewer parameters
\WORLD\
reference :
How to assign the output of a program to a variable in a DCL com script on VMS?
The usual way to do this is to write the output to a file and read from the file and put that into a DCL symbol (or logical). Although not obvious, you can do this with the PIPE command was well:
$ pipe r 2words
hello world
$ pipe r 2words |(read sys$pipe line ; line=""""+line+"""" ; def/job value &line )
$ sh log value
"VALUE" = "hello world" (LNM$JOB_85AB4440)
$
IF you are able to change the program, add some code to it to write the required values into symbols or logicals (see LIB$ routines)
If you can modify the program, using LIB$SET_SYMBOL in the program defines a DCL symbol (what you are calling a variable) for DCL. That's the cleanest way to do this. If it really needs to be a logical, then there are system calls that define logicals.

dcl assignment from a command

I am new to DCL.
I want to get the out put of a command in a variable and iterate result one by one.
filePath=dir /since="time_now" [.SUBDIR]*.PNG/noheader/notrail
That's just not how we roll with DCL.
We don't do pipes, we do, but not really.
DIR/SINCE=NOW ... will not give anything by definition, since nothing exists since now.
Use /OUT to stick the directory output into a file, and then read ans parse (F$PARSE and/or F$ELEMENT and/or F$LOC)
Check out HELP OPEN; HELP READ [/END]; HELP LEXICAL
Google for examples.
More advanced DCL scripts use F$PARSE, F$SEARCH and F$FILE(file,CDT) to avoid activating images and creating temp files: $ HELP LEXICAL
Google for examples.
Check out yesterday stack-exhange entry ?! : OpenVMS - DELETE Line if TEXT like x
But if you are just starting... IMHO just skip DCL and stick to PERL
$ perl -e "for (<[.SUBDIR]*.PNG>) { next unless -M > 0.123; print; ... }"
Good luck!
Hein
top:
file = f$search("[.subdir]*.PNG")
if (file .eqs. "")then goto cont
mtime=f$file_attribute(file,"RDT")
if mtime.ges.build_start_time then -
name=f>parse(file,,,"NAME")
call CHECK "''name'"
goto top
cont:
#Hein please review this code and suggest changes

Why doesn't io:write() write to the output file?

I'm writing a short script in Lua to replicate Search/Replace functionality. The goal is to enter a search term and a replacement term, and it will comb through all the files of a given extension (not input-determined yet) and replace the Search term with the Replacement term.
Everything seems to do what it's supposed to, except the files are not actually written to. My Lua interpreter (compiled by myself in Pelles-C) does not throw any errors or exit abnormally; the script completes as if it worked.
At first I didn't have i:flush(), but I added it after reading that it is supposed to save any written data to the file (see LUA docs). It didn't change anything, and files are still not written to.
I think it might have something to do with how I'm opening the file to edit it, since the "w" option works (but overwrites everything in my test files).
Source:
io.write("Enter your search term:")
term = io.read()
io.write("Enter your replace term:")
replacement = io.read()
io.stdin:read()
t = {}
for z in io.popen('dir /b /a-d'):lines() do
if string.match(string.lower(z), "%.txt$") then
print(z)
table.insert(t, z)
end
end
print("Second loop")
for _, w in pairs(t) do
print(w)
i = io.open(w, "r+")
print(i)
--i:seek("set", 6)
--i:write("cheese")
--i:flush()
for y in i:lines() do
print(y)
p, count = string.gsub(y, term, replacement, 1)
print(p)
i:write(p)
i:flush()
io.stdin:read()
end
i:close()
end
This is the output I get (which is what I want to happen), but in reality isn't being written to the file:
There was one time where it wrote output to a file, but it only output to one file and after that write my script crashed with the message: No error. The line number was at the for y in i:lines() do line, but I don't know why it broke there. I've noticed file:lines() will break if the file itself has nothing in it and give an odd/gibberish error, but there are things in my text files.
Edit1
I tried do this in my for loop:
for y in i:lines() do
print(y)
p, count = string.gsub(y, term, replacement, 1)
print(p)
i:write(p)
i:seek("set", 3) --New
i:write("TESTESTTEST") --New
i:flush()
io.stdin:read()
end
in order to see if I could force it to write regular text. It does but then it crashes with No error and still doesn't write the replacement string (just TESTESTTEST). I don't know what the problem could be.
I guess, one can't write to file while traversing its lines
for y in i:lines() do
i:write(p)
i:flush()
end

awk getline skipping to last line -- possible newline character issue

I'm using
while( (getline line < "filename") > 0 )
within my BEGIN statement, but this while loop only seems to read the last line of the file instead of each line. I think it may be a newline character problem, but really I don't know. Any ideas?
I'm trying to read the data in from a file other than the main input file.
The same syntax actually works for one file, but not another, and the only difference I see is that the one for which it DOES work has "^M" at the end of each line when I look at it in Vim, and the one for which it DOESN'T work doesn't have ^M. But this seems like an odd problem to be having on my (UNIX based) Mac.
I wish I understood what was going with getline a lot better than I do.
You would have to specify RS to something more vague.
Here is a ugly hack to get things working
RS="[\x0d\x0a\x0d]"
Now, this may require some explanation.
Diffrent systems use difrent ways to handle change of line.
Read http://en.wikipedia.org/wiki/Carriage_return and http://en.wikipedia.org/wiki/Newline if you are
interested in it.
Normally awk hadles this gracefully, but it appears that in your enviroment, some files are being naughty.
0x0d or 0x0a or 0x0d 0x0a (CR+LF) should be there, but not mixed.
So lets try a example of a mixed data stream
$ echo -e "foo\x0d\x0abar\x0d\x0adoe\x0arar\x0azoe\x0dqwe\x0dtry" |awk 'BEGIN{while((getline r )>0){print "r=["r"]";}}'
Result:
r=[foo]
r=[bar]
r=[doe]
r=[rar]
try]oe
We can see that the last lines are lost.
Now using the ugly hack to RS
$ echo -e "foo\x0d\x0abar\x0d\x0adoe\x0arar\x0azoe\x0dqwe\x0dtry" |awk 'BEGIN{RS="[\x0d\x0a\x0d]";while((getline r )>0){print "r=["r"]";}}'
Result:
r=[foo]
r=[bar]
r=[doe]
r=[rar]
r=[zoe]
r=[qwe]
r=[try]
We can see every line is obtained, reguardless of the 0x0d 0x0a junk :-)
Maybe you should preprocess your input file with for example dos2unix (http://sourceforge.net/projects/dos2unix/) utility?