I need to define a macro variable that can take three string literals. The string literals are separated by a pipe character ("|"), which is thus being used as an "OR" operator. The string literals are the full names of three people so present certain challenges when it comes to coding. The code I am having issues with is:
%let string= John F\. Kennedy | %quote(John F. Kennedy, Jr.) | Kelly O'Donnell;
As can be seen from the code snippet:
1) The first name has a period (.) so I "escaped" it using a backslash. No issues for me here.
2) The second name has a comma (,) so I enclosed the entire name in %quote(). Again, no issues for me here.
3) The third name has a single quote ('). I tried putting a backslash in front of the quote, or using the %quote() method. Neither of these methods work for me, and all code after the apostrophe is treated as one long string. How can I appropriately "escape" the single quote in the third name?
The code snippet above is a part of the bigger code below. The code is attempting to look for the three names in the corporate filings of companies.
data ncsr1; set wrdssec.wrds_forms; format FNAME2 $100. ; where form = "N-CSR" and year(FDATE) = 2018; FNAME2 = cats("/wrds/sec/wrds_clean_filings/",WRDSFNAME); drop FINDEXDATE LINDEXDATE FNAME WRDSFNAME; run; %let string= John F\. Kennedy | %quote(John F. Kennedy, Jr.) | Kelly O'Donnell; %let paragraph_length=0; %TEXTPARSE(inset=ncsr1,outset=ncsr2,fname_full=fname2,tstr= &string, ln= ¶graph_length);
You don't have to escape (SAS docs call this quoting, many SAS folks refer to it as masking) a period. You do have to mask the apostrophe, and the comma. If you are hard-coding the string, the easiest way to mask these values is with %str().
%let string= John F. Kennedy | John F. Kennedy%str(,) Jr. | Kelly O%str(%')Donnell;
%put &=string;
%let paragraph_length=0;
%macro TEXTPARSE(inset=,outset=,fname_full=,tstr=,ln=) ;
%put &=tstr ;
%mend TEXTPARSE ;
%TEXTPARSE(inset=ncsr1,outset=ncsr2,fname_full=fname2,tstr= &string, ln= ¶graph_length)
Note that depending on the code inside of your TEXTPARSE macro, it may be unquoting (unmasking) the problematic characters. So it's possible when you run this you will still get errors. If that's the case, please show an example of your TEXTPARSE macro which reproduces the problem. The answer will likely be to add more quoting inside the macro.
I'm confused by your comment that the pipe will be used as a logical OR in your macro. I don't see how that could work with your current string, because you cannot have code like:
%if &name = John F. Kennedy | John F. Kennedy%str(,) Jr. | Kelly O%str(%')Donnel ;
Perhaps you are looping over this pipe-delimited list and generating a valid OR expression, such as:
%if &name = John F. Kennedy | &name = John F. Kennedy%str(,) Jr. | &name = Kelly O%str(%')Donnel ;
Obviously, the result you want needs to be sent through macro %TEXTPARSE in order to work, and you don't provide the code in that macro, so we can't help directly with that part unless you provide us with that code.
Nevertheless, this works:
%let string= John F\. Kennedy | John F. Kennedy, Jr. | Kelly O%str(%')Donnell;
%put &=string;
%let substr1 = %qscan(%bquote(&string),1,|); %put &=substr1;
%let substr2 = %qscan(%bquote(&string),2,|); %put &=substr2;
%let substr3 = %qscan(%bquote(&string),3,|); %put &=substr3;
It also works without the backslash
Why do you think that the period would cause any trouble? That is not one of the special characters to the SAS macro language.
Why do you think that using a backslash "escapes" the period? Are you planning to use that string to generate a Regular Expression at some point down the line?
Why don't you just add actual quotes around the whole thing and then the macro processor will ignore all of the characters that are special to it. If the goal is to use the values to generate SAS code then you will need quotes around the strings anyway. For the string with the single quote you an either use double quotes on the outside
%let string='John F. Kennedy'|'John F. Kennedy, Jr.'|"Kelly O'Donnell";
or when using single quotes double them up.
%let string='John F. Kennedy'|'John F. Kennedy, Jr.'|'Kelly O''Donnell';
If you really cannot add actual quotes you can use the %BQUOTE() function to add macro quoting instead.
%let string=%bquote(John F. Kennedy|John F. Kennedy, Jr.|Kelly O'Donnell);
And if you are going to use the string in some regular expression then add the backslashes where RegEx needs them.
%let string=%bquote(John F\. Kennedy|John F\. Kennedy\, Jr\.|Kelly O\'Donnell);
You don't have to escape (SAS docs call this quoting, many SAS folks refer to it as masking) a period. You do have to mask the apostrophe, and the comma. If you are hard-coding the string, the easiest way to mask these values is with %str().
%let string= John F. Kennedy | John F. Kennedy%str(,) Jr. | Kelly O%str(%')Donnell;
%put &=string;
%let paragraph_length=0;
%macro TEXTPARSE(inset=,outset=,fname_full=,tstr=,ln=) ;
%put &=tstr ;
%mend TEXTPARSE ;
%TEXTPARSE(inset=ncsr1,outset=ncsr2,fname_full=fname2,tstr= &string, ln= ¶graph_length)
Note that depending on the code inside of your TEXTPARSE macro, it may be unquoting (unmasking) the problematic characters. So it's possible when you run this you will still get errors. If that's the case, please show an example of your TEXTPARSE macro which reproduces the problem. The answer will likely be to add more quoting inside the macro.
I'm confused by your comment that the pipe will be used as a logical OR in your macro. I don't see how that could work with your current string, because you cannot have code like:
%if &name = John F. Kennedy | John F. Kennedy%str(,) Jr. | Kelly O%str(%')Donnel ;
Perhaps you are looping over this pipe-delimited list and generating a valid OR expression, such as:
%if &name = John F. Kennedy | &name = John F. Kennedy%str(,) Jr. | &name = Kelly O%str(%')Donnel ;
You were correct. I was incorrectly assuming the pipe was being used as an OR operator. I am working around that issue myself. As for my original question, it appears using %str() to mask commas and apostrophes in the names helps. Cheers!
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
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.