Hi all,
I'm using fget() to read records from an external file into a SAS variable. Everything works except that leading blanks aren't kept (=string in SAS variable starts with first non-blank character).
Any help how to keep the leading blanks would be really appreciated. I simply can't make it work.
Below self contained code sample showcasing the challenge.
1. Create sample file
%let source_file=%sysfunc(pathname(work))\myscript.sas;
data _null_;
infile datalines truncover;
file "&source_file";
input;
put _infile_;
datalines4;
data sample;
set sashelp.class;
run;
;;;;
2. Syntax reading the sample file that keeps the leading blanks
data _null_;
file print;
infile "&source_file" lrecl=132;
input;
put _infile_;
run;
3. Syntax using fget() that doesn't keep the leading blanks
/* here the code I want to use BUT need to keep leading blanks from source file */
data _null_;
file print;
length _filrf $8 _instr $132;
informat _instr $char132.;
_filrf='demo';
_rc=filename(_filrf, cats("&source_file"));
_fid=fopen(_filrf);
if _fid > 0 then
do while(fread(_fid)=0);
_rc=fget(_fid, _instr, 132);
put _instr;
end;
_rc=fclose(_fid);
_rc=filename(_filrf);
run;
The real problem I need to solve
I've got a set of main programs with %includes to other programs - and the %included programs can have further %includes ("cascading %includes")
I want to get rid of the includes by creating new main programs that got all the %included code directly in the main script.
I've got a working solution using #3 syntax but it's not acceptable to loose all the code indention when generating the new scripts.
Should there be no solution to keep the leading blanks with my approach then I take accept more than happily also other coding approaches that solve my actual problem.
The solution needs to work under Windows and Unix. That's why I went for an approach using SAS.
Hi @Patrick,
I think FGET did read the leading blanks. It's just that the PUT statement using list PUT didn't write them. With formatted PUT, e.g.
put _instr $132.;
they appear.
Edit: Also, the INFORMAT statement doesn't seem to be necessary.
Using informat $char. :
%let source_file=%sysfunc(pathname(work))\myscript.sas;
data _null_;
infile datalines truncover;
file "&source_file";
input x $char100.;
put x $char100.;
datalines4;
data sample;
set sashelp.class;
run;
;;;;
Hi @Ksharp
You probably haven't really read the whole question?
Writing the sample file works and is not the issue/question asked. It's about reading the sample file using data step functions. Because I want to read .sas files with %include statements and create a single .sas files with all the code as result, I have switch the external file whenever I encounter an %include, read the whole %included file, and then switch back to the main programs and continue reading the records after the %include statement. That's why I'm using data step functions also to define and open the external file.
Thanks,
Patrick
Then may-be just answer questions where you can spend the necessary time for reading and understanding the problem.
I believe I've got sufficient experience to decide what answers get me further but you might send beginners on the wrong path if not really addressing their problem.
Hi @Patrick,
I think FGET did read the leading blanks. It's just that the PUT statement using list PUT didn't write them. With formatted PUT, e.g.
put _instr $132.;
they appear.
Edit: Also, the INFORMAT statement doesn't seem to be necessary.
Thank you so much! Tried so many things but not this very simple one.
Do you also have an explanation why using an explicit format has this effect?
True, the informat has no effect. I've only added it to the sample code so no one is going to propose it....
@Patrick wrote:
Do you also have an explanation why using an explicit format has this effect?
This is one of the differences between formatted output and list output. The documentation of the latter says in section "Using List Output":
"Character values are left-aligned in the field; leading and trailing blanks are removed. To include blanks (in addition to the blank inserted after each value), use formatted or column output instead of list output."
Thank you very much @FreelanceReinh - Learned something 🙂
I believe I was so far only fully aware of the different styles for reading external data but not for writing it.
I've ended up using format &varying. to not pad all the records with up to 132 blanks.
data _null_;
file print;
length _filrf $8 _instr $132;
informat _instr $char132.;
_filrf='demo';
_rc=filename(_filrf, cats("&source_file"));
_fid=fopen(_filrf);
if _fid > 0 then
do while(fread(_fid)=0);
_rc=fget(_fid, _instr, 132);
_l=lengthn(_instr);
put _instr $varying. _l;
end;
_rc=fclose(_fid);
_rc=filename(_filrf);
run;
Join us for SAS Innovate 2025, our biggest and most exciting global event of the year, in Orlando, FL, from May 6-9. Sign up by March 14 for just $795.
Learn how use the CAT functions in SAS to join values from multiple variables into a single value.
Find more tutorials on the SAS Users YouTube channel.
Ready to level-up your skills? Choose your own adventure.