BookmarkSubscribeRSS Feed
☑ This topic is solved. Need further help from the community? Please sign in and ask a new question.
Tasneem
Calcite | Level 5

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= &paragraph_length);
1 ACCEPTED SOLUTION

Accepted Solutions
Quentin
Super User

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= &paragraph_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 ;
The Boston Area SAS Users Group is hosting free webinars!
Next webinar will be in January 2025. Until then, check out our archives: https://www.basug.org/videos. And be sure to subscribe to our our email list.

View solution in original post

4 REPLIES 4
PaigeMiller
Diamond | Level 26

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 

--
Paige Miller
Tom
Super User Tom
Super User

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);
Quentin
Super User

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= &paragraph_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 ;
The Boston Area SAS Users Group is hosting free webinars!
Next webinar will be in January 2025. Until then, check out our archives: https://www.basug.org/videos. And be sure to subscribe to our our email list.
Tasneem
Calcite | Level 5

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: Save the Date

 SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!

Save the date!

How to Concatenate Values

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.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 4 replies
  • 4625 views
  • 1 like
  • 4 in conversation