TOPIC: RECURSION
AND & OR, a cautionary tale
27th March 2009The inspiration for this post is a situation where having the string "OR" or "AND" as an input to a piece of SAS Macro code, breaking a program that I had written. Here is a simplified example of what I was doing:
%macro test;
%let doms=GE GT NE LT LE AND OR;
%let lv_count=1;
%do %while (%scan(&doms,&lv_count,' ') ne );
%put &lv_count;
%let lv_count=%eval(&lv_count+1);
%end;
%mend test;
%test;
The loop proceeds well until the string "AND" is met and "OR" has the same effect. The result is the following message appears in the log:
ERROR: A character operand was found in the %EVAL function or %IF condition where a numeric operand is required. The condition was: %scan(&doms,&lv_count,' ') ne
ERROR: The condition in the %DO %WHILE loop, , yielded an invalid or missing value, . The macro will stop executing.
ERROR: The macro TEST will stop executing.
Both AND & OR (case doesn't matter, but I am sticking with upper case for sake of clarity) seem to be reserved words in a macro DO WHILE loop, while equality mnemonics like GE cause no problem. Perhaps, the fact that and equality operator is already in the expression helps. Regardless, the fix is simple:
%macro test;
%let doms=GE GT NE LT LE AND OR;
%let lv_count=1;
%do %while ("%scan(&doms,&lv_count,' ')" ne "");
%put &lv_count;
%let lv_count=%eval(&lv_count+1);
%end;
%mend test;
%test;
Now none of the strings extracted from the macro variable &DOMS
will appear as bare words and confuse the SAS Macro processor, but you do have to make sure that you are testing for the null string ("" or '') or you'll send your program into an infinite loop, always a potential problem with DO WHILE
loops so they need to be used with care. All in all, an odd-looking message gets an easy solution without recourse to macro quoting functions like %NRSTR
or %SUPERQ
.
Recursive FTP with the command line
6th August 2008Here's a piece of Linux/UNIX shell scripting code that will do a recursive FTP refresh of a website for you:
lftp <<~/Tmp/log_file.tmp 2>>~/Tmp/log_file.tmp
open ${HOSTNAME}
user ${USER} ${PSSWD}
mirror -R -vvv "${REP_SRC}" "${REP_DEST}"
EndFTP
When my normal FTP scripting approach left me with a broken WordPress installation and an invalid ticket in the project's TRAC system that I had to close, I turned to looking for a more robust way of achieving the website updates and that's what led me to seek out the options available for FTP transfers that explicitly involve directory recursion. The key pieces in the code above are the use of lftp
in place of ftp
, my more usual tool for the job, and the invocation of the mirror command that comes with lftp
. The -R
switch ensures that file transfer is from local to remote (vice versa is the default) and -vvv
turns on maximum verbosity, a very useful thing when you find that it takes longer than more usual means. It's all much slicker than writing your own script to do the back-work of ploughing through the directory structure and ensuring that the recursive transfers take place. Saying that, it is possible to have a one line variant of the above, but the way that I have set things up might be more familiar to users of ftp
.