I need to convert non SAS character input to calculated size numeric, and I can't find my mistake(s):
data _null_;
input space $11.;
size=inputn(space,cats('comma',length(space)-1,'.'));
select (char(space,length(space)));
when ('k') size=size*1000;
when ('m') size=size*1000**2;
when ('g') size=size*1000**3;
otherwise do;
put 'space not recognized= ' space;
abort abend 055;
end;
end;
cards;
23436.000K
0.000K
50.688K
1340.160M
837.600K
47.190K
1187.640M
55.872K
;
run;
I have pieced this together with other code. I'm not the strongest SAS coder. The INPUTN function seems to work the way I need it to. Simply remove the trailing size identifier and convert to numeric. The problem lies in the SELECT, it puts the first SPACE card without trailing identifier. What am I doing wrong?
"k" and "K" are not the same thing. Easy to correct though.
Correct. Still does not resolve the issue.
What I receive:
SPACE NOT RECOGNIZED= 23436.000
OK, rather than picking this apart and trying to diagnose where it went wrong, why not make your life easy?
input space 10. magnitude $ 11;
Including ABORT statements for a condition you are asking about is sort of counterproductive as your code kills any chance of seeing what is happening with the data.
data junk; input space $11.; size=inputn(space,cats('comma',length(space)-1,'.')); select (char(space,length(space))); when ('k','K') size=size*1000; when ('m','M') size=size*1000**2; when ('g','G') size=size*1000**3; otherwise do; put 'space not recognized= ' space; /* abort abend 055; */ end; end; cards; 23436.000K 0.000K 50.688K 1340.160M 837.600K 47.190K 1187.640M 55.872K ; run;
Or Upcase the result of the Char.
ballardw,
Thanks for the input. I would think that this gets me close to what I need but when I run your code it flags all CARD inputs in the OTHERWISE statement. In my logic, it shouldn't be hitting the OTHERWISE statement with the inputs set here.
I need the program to stop processing when it encounters anything other than a K,M or G for the suffix. Is this the wrong way to code it?
Your data has an uppercase K but that character it is not listed in any of the values in your WHEN statements. Also don't abort your whole SAS session just because of one unexpected value.
data test;
input space $11.;
size=inputn(space,cats('comma',length(space)-1,'.'));
select (lowcase(char(space,length(space))));
when ('k') size=size*1000;
when ('m') size=size*1000**2;
when ('g') size=size*1000**3;
otherwise do;
invalid=1;
put 'Suffix not recognized ' space=$quote.;
end;
end;
cards;
23436.000K
0.000K
50.688K
1340.160M
837.600K
47.190K
1187.640M
55.872K
123A
;
proc print;
format size comma20.;
run;
Obs space size invalid 1 23436.000K 23,436,000 . 2 0.000K 0 . 3 50.688K 50,688 . 4 1340.160M 1,340,160,000 . 5 837.600K 837,600 . 6 47.190K 47,190 . 7 1187.640M 1,187,640,000 . 8 55.872K 55,872 . 9 123A 123 1
Thanks for the input Tom. I believe you were the one that initially helped me with this code. But when I run your exact code below (on a mainframe) it flags all the input cards as invalid and is not calculating the size. I also need this program to stop/end/abort if it encounters anything other than a K,M or G suffix.
OBS SPACE SIZE INVALID
1 23436.000 23,436 1
2 0.000 0 1
3 50.688 51 1
4 1340.160 1,340 1
5 837.600 838 1
6 47.190 47 1
7 1187.640 1,188 1
8 55.872 56 1
9 123A 123 1
SUFFIX NOT RECOGNIZED SPACE="23436.000"
SUFFIX NOT RECOGNIZED SPACE="0.000"
SUFFIX NOT RECOGNIZED SPACE="50.688"
SUFFIX NOT RECOGNIZED SPACE="1340.160"
SUFFIX NOT RECOGNIZED SPACE="837.600"
SUFFIX NOT RECOGNIZED SPACE="47.190"
SUFFIX NOT RECOGNIZED SPACE="1187.640"
SUFFIX NOT RECOGNIZED SPACE="55.872"
SUFFIX NOT RECOGNIZED SPACE="123A"
There is something with positioning on the mainframe. I ran the following, with the inputs aligned under the CARDS statement:
data test;
input space $11.;
size=inputn(space,cats('comma',length(space)-1,'.'));
suffix=(char(space,length(space)));
cards;
23436.000K
0.000K
50.688K
1340.160M
837.600K
47.190K
1187.640M
55.872K
123A
;
proc print;
run;
I received my desirable results:
OBS SPACE SIZE SUFFIX 1 23436.000K 23436.00 K 2 0.000K 0.00 K 3 50.688K 50.69 K 4 1340.160M 1340.16 M 5 837.600K 837.60 K 6 47.190K 47.19 K 7 1187.640M 1187.64 M 8 55.872K 55.87 K 9 123A 123.00 A
Your previous example is showing that you never read the last character of the string into the character variable. Why did you only read the first 11 bytes on the line? Why not just read more? When writing a program with in-line data DO NOT INDENT the data. To make it clearer that you don't want to indent make sure to place the CARDS (or DATALINES) statement itself in column one.
Also to improve the logic have it only remove the last character if it is not a digit. See if you can figure out how to modify the code to do that.
Tom,
I'm reading in a report dumped to a file to pull relevant data off of. This is to become a billing job, with space being the unit to be billed. The report is fixed length and the space field looks to be set at 11 bytes. The variable itself (I'm calling it space) is in a unique format that needs to be converted to gigabytes.
VOLSER DATA SET NAME ADATE BYTES CAT
PRDA02 SYS2.NFCTEST.FDREPORT.TERSED 2021.012 829.440K NO .......
ZMF015 CHGMAN.W.XITCAW.#D913DD0.#0592618 2021.012 55.840K NO
ZMF015 CHGMAN.W.NFA31.#D911493.#8C68F7C 2021.012 55.840K NO
ZMF015 CHGMAN.W.XITCAW.#D90B107.#B41650E.OUTLIST 2021.012 839.940K NO
ZMF015 CHGMAN.W.XITCAW.#D90C400.#91A2E30.OUTLIST 2021.012 839.940K NO
ZMF007 CHGMAN.W.XITCAW.#D90C1F5.#0CC9442 2021.012 55.840K NO
ZMF008 CHGMAN.W.XITCAW.#D90C447.#0A5E04A.OUTLIST 2021.012 839.940K NO
ZMF008 CHGMAN.W.XITCAW.#D90C443.#D18977A.OUTLIST 2021.012 839.940K NO
ZMF002 CHGMAN.W.XITCAW.#D90C3FA.#FC2A238.OUTLIST 2021.012 839.940K NO
ZMF004 CHGMAN.W.XITCAW.#D90B0BB.#C4A5A4A.OUTLIST 2021.012 839.940K NO
DEVA00 NFCD.TESTLOAD.MAINPPUB 2021.012 286035.000K YES
DEVA03 NFCD.TESTLOAD.PARA.PDSE 2021.012 15724.800K YES
DEVA04 NFCDABCO.CNTL.PAT 2021.012 9883.680K YES
DEVA04 NFCD.TESTLOAD.ASDUAT 2021.012 204228.990K YES
DEVA04 NFCD.TESTLOAD.ASDPARA 2021.012 342097.860K YES
........
FINAL TOTALS --
BYTES------------263.060G
There are more fields to the right and a ton more records but this shows what I'm working with. If it were up to me, I would just write a quick Assembler job to handle this as I'm not proficient in SAS (obviously). I need to ignore the header/footer records. This data is not mine and I'm unfamiliar with it but this will feed invoicing so it is very sensitive. I'm trying to code a robust enough SAS job to handle any situation. Based on the limited amount of data I've received, it seems that the report converts the space to either kilobytes, megabytes or gigabytes. The space field needs to be converted to a common size, bytes in my case. The program must stop if any error is encountered with the conversion. Otherwise it will continue to invoice incorrectly.
Here is my attempt with your help from before:
DATA USER.FDREPORT; INFILE INFILE; INPUT @1 VOLSER $6. @8 DSNAME $44. @53 ARCDT $8. @62 SPACE $11. @74 CATALOG $3. @78 EXPDT $8. @87 RUNDT $8.; IF _N_ = 1 THEN DELETE; IF _INFILE_ =: "FINAL TOTALS" THEN DELETE; IF _INFILE_ =: "BYTES" THEN DELETE; SIZE=INPUTN(SPACE,CATS('COMMA',LENGTH(SPACE)-1,'.')); SELECT (CHAR(SPACE,LENGTH(SPACE))); WHEN ('k','K') SIZE=SIZE*1024; WHEN ('m','M') SIZE=SIZE*1024**2; WHEN ('g','G') SIZE=SIZE*1024**3; OTHERWISE DO; PUT 'SUFFIX NOT RECOGNIZED ' SPACE=$QUOTE.; ABORT ABEND 055; END; END; ARCDATE=INPUT(COMPRESS(ARCDT,'.'),JULIAN7.); EXPDATE=INPUT(COMPRESS(EXPDT,'.'),JULIAN7.); RUNDATE=INPUT(COMPRESS(RUNDT,'.'),JULIAN7.); KEEP VOLSER DSNAME ARCDATE SIZE CATALOG EXPDATE RUNDATE; RUN;
This is failing, I believe, on the first header record.
If the header line only appears once you can skip the header line use FIRSTOBS=2 option on the INFILE statement.
INFILE INFILE firstobs=2;
If the header line repeats (that is you are reading a print-out that repeats the header at the start of each page) then you will need to use a different method to identify the header line and skip it.
input ...
if volser='VOLSER' then delete;
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!
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.