<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Find and replace line feeds ('0A'x) within a CSV file in SAS Programming</title>
    <link>https://communities.sas.com/t5/SAS-Programming/Find-and-replace-line-feeds-0A-x-within-a-CSV-file/m-p/703783#M215698</link>
    <description>&lt;P&gt;Hi,&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I have a CSV file with line feeds&amp;nbsp;('0A'x) appearing occasionally (I think someone typed in "hard" carriage returns during data entry). The lines correctly end with a carriage return line feed (CRLF '0D'x '0A'x) pair. I want to remove the "stand alone" line feeds, and keep the&amp;nbsp;carriage return line feed pairs intact.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I have tried using the code described here (reproduced below):&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;A href="https://support.sas.com/kb/26/065.html" target="_blank"&gt;https://support.sas.com/kb/26/065.html&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;This works, but some of the line feeds are missed, as they are not all within double quotation marks. Can someone help, please?&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;/* Create sample .csv file containing CR/LF bytes.  '0D'x is the */
/* hexadecimal representation of CR and '0A'x is the hexadecimal */
/* representation of LF.                                         */

data _null_;
  file "c:\sample.csv";  
  /* Code the PUT statement so the hex values will be inside the */
  /* the double quotes in the output file SAMPLE.CSV.            */
  put '"field1","field2","field3'
    '0D'x    
    '",'
    '"field4","field5","field6'
    '0A'x   
    '",'
    '"field7","field8","field9"'
  ;
run;

/* Read in the test file created above. */
data out;
  /* The DSD option assumes the delimiter is a comma. You can override */
  /* the delimiter with the DLM= option if needed.                     */
  infile "c:\sample.csv" dsd truncover;
  length var1 - var9 $15;
  input var1 - var9 $;
run;

proc print;
  title 'File is read incorrectly due to embedded CR/LF';
run;

/************************** CAUTION ***************************/
/*                                                            */
/* This program UPDATES IN PLACE, create a backup copy before */
/* running.                                                   */
/*                                                            */
/************************** CAUTION ***************************/
                                                           
/* Replace carriage return and linefeed characters inside     */
/* double quotes with a specified character.  This sample     */
/* uses '@' and '$', but any character can be used, including */
/* spaces.  CR/LFs not in double quotes will not be replaced. */


%let repA='@';                    /* replacement character LF */
%let repD='$';                    /* replacement character CR */

                             
%let dsnnme="c:\sample.csv";      /* use full path of CSV file */

data _null_;
  /* RECFM=N reads the file in binary format. The file consists    */
  /* of a stream of bytes with no record boundaries.  SHAREBUFFERS */
  /* specifies that the FILE statement and the INFILE statement    */
  /* share the same buffer.                                        */
  infile &amp;amp;dsnnme recfm=n sharebuffers;
  file &amp;amp;dsnnme recfm=n;

  /* OPEN is a flag variable used to determine if the CR/LF is within */
  /* double quotes or not.  Retain this value.                        */
  retain open 0;

  input a $char1.;
  /* If the character is a double quote, set OPEN to its opposite value. */
  if a = '"' then open = ^(open);

  /* If the CR or LF is after an open double quote, replace the byte with */
  /* the appropriate value.                                               */
  if open then do;
    if a = '0D'x then put &amp;amp;repD;
    else if a = '0A'x then put &amp;amp;repA;
  end;
run;

/* Read in new version of file to check for success. */
data outp;
  infile "c:\sample.csv" dsd dlm=',' truncover;
  length var1 - var9 $ 15;
  input var1 - var9 $ ;
run;

proc print;
  title1 'File is read correctly after transformation ';
  title2 "Look for printable characters &amp;amp;repa &amp;amp;repd in variable values ";
run;

/* OPTIONAL -- Delete external file */
data _null_;
  fname="tempfile";
  rc=filename(fname,"c:\sample.csv");
  if rc = 0 and fexist(fname) then rc=fdelete(fname);
  rc=filename(fname);
run;&lt;/CODE&gt;&lt;/PRE&gt;</description>
    <pubDate>Sat, 05 Dec 2020 09:00:36 GMT</pubDate>
    <dc:creator>Norman21</dc:creator>
    <dc:date>2020-12-05T09:00:36Z</dc:date>
    <item>
      <title>Find and replace line feeds ('0A'x) within a CSV file</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Find-and-replace-line-feeds-0A-x-within-a-CSV-file/m-p/703783#M215698</link>
      <description>&lt;P&gt;Hi,&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I have a CSV file with line feeds&amp;nbsp;('0A'x) appearing occasionally (I think someone typed in "hard" carriage returns during data entry). The lines correctly end with a carriage return line feed (CRLF '0D'x '0A'x) pair. I want to remove the "stand alone" line feeds, and keep the&amp;nbsp;carriage return line feed pairs intact.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I have tried using the code described here (reproduced below):&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;A href="https://support.sas.com/kb/26/065.html" target="_blank"&gt;https://support.sas.com/kb/26/065.html&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;This works, but some of the line feeds are missed, as they are not all within double quotation marks. Can someone help, please?&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;/* Create sample .csv file containing CR/LF bytes.  '0D'x is the */
/* hexadecimal representation of CR and '0A'x is the hexadecimal */
/* representation of LF.                                         */

data _null_;
  file "c:\sample.csv";  
  /* Code the PUT statement so the hex values will be inside the */
  /* the double quotes in the output file SAMPLE.CSV.            */
  put '"field1","field2","field3'
    '0D'x    
    '",'
    '"field4","field5","field6'
    '0A'x   
    '",'
    '"field7","field8","field9"'
  ;
run;

/* Read in the test file created above. */
data out;
  /* The DSD option assumes the delimiter is a comma. You can override */
  /* the delimiter with the DLM= option if needed.                     */
  infile "c:\sample.csv" dsd truncover;
  length var1 - var9 $15;
  input var1 - var9 $;
run;

proc print;
  title 'File is read incorrectly due to embedded CR/LF';
run;

/************************** CAUTION ***************************/
/*                                                            */
/* This program UPDATES IN PLACE, create a backup copy before */
/* running.                                                   */
/*                                                            */
/************************** CAUTION ***************************/
                                                           
/* Replace carriage return and linefeed characters inside     */
/* double quotes with a specified character.  This sample     */
/* uses '@' and '$', but any character can be used, including */
/* spaces.  CR/LFs not in double quotes will not be replaced. */


%let repA='@';                    /* replacement character LF */
%let repD='$';                    /* replacement character CR */

                             
%let dsnnme="c:\sample.csv";      /* use full path of CSV file */

data _null_;
  /* RECFM=N reads the file in binary format. The file consists    */
  /* of a stream of bytes with no record boundaries.  SHAREBUFFERS */
  /* specifies that the FILE statement and the INFILE statement    */
  /* share the same buffer.                                        */
  infile &amp;amp;dsnnme recfm=n sharebuffers;
  file &amp;amp;dsnnme recfm=n;

  /* OPEN is a flag variable used to determine if the CR/LF is within */
  /* double quotes or not.  Retain this value.                        */
  retain open 0;

  input a $char1.;
  /* If the character is a double quote, set OPEN to its opposite value. */
  if a = '"' then open = ^(open);

  /* If the CR or LF is after an open double quote, replace the byte with */
  /* the appropriate value.                                               */
  if open then do;
    if a = '0D'x then put &amp;amp;repD;
    else if a = '0A'x then put &amp;amp;repA;
  end;
run;

/* Read in new version of file to check for success. */
data outp;
  infile "c:\sample.csv" dsd dlm=',' truncover;
  length var1 - var9 $ 15;
  input var1 - var9 $ ;
run;

proc print;
  title1 'File is read correctly after transformation ';
  title2 "Look for printable characters &amp;amp;repa &amp;amp;repd in variable values ";
run;

/* OPTIONAL -- Delete external file */
data _null_;
  fname="tempfile";
  rc=filename(fname,"c:\sample.csv");
  if rc = 0 and fexist(fname) then rc=fdelete(fname);
  rc=filename(fname);
run;&lt;/CODE&gt;&lt;/PRE&gt;</description>
      <pubDate>Sat, 05 Dec 2020 09:00:36 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Find-and-replace-line-feeds-0A-x-within-a-CSV-file/m-p/703783#M215698</guid>
      <dc:creator>Norman21</dc:creator>
      <dc:date>2020-12-05T09:00:36Z</dc:date>
    </item>
    <item>
      <title>Re: Find and replace line feeds ('0A'x) within a CSV file</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Find-and-replace-line-feeds-0A-x-within-a-CSV-file/m-p/703794#M215699</link>
      <description>&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Since you are working in Windows you might try the Infile option TRMSTR to specify that you need a combination of CR and LF to terminate a line.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="markup"&gt;data out;
  /* The DSD option assumes the delimiter is a comma. You can override */
  /* the delimiter with the DLM= option if needed.                     */
  infile "c:\sample.csv" dsd truncover   TRMSTR=CRLF;
  length var1 - var9 $15;
  input var1 - var9 $;
run;&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Your statement&lt;/P&gt;
&lt;PRE class="language-sas"&gt;&lt;CODE&gt;'File is read incorrectly due to embedded CR/LF';&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Is not quite correct. CR/LF is actualy TWO characters, you are typically encountering only the LF, a single character.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Sat, 05 Dec 2020 10:05:10 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Find-and-replace-line-feeds-0A-x-within-a-CSV-file/m-p/703794#M215699</guid>
      <dc:creator>ballardw</dc:creator>
      <dc:date>2020-12-05T10:05:10Z</dc:date>
    </item>
    <item>
      <title>Re: Find and replace line feeds ('0A'x) within a CSV file</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Find-and-replace-line-feeds-0A-x-within-a-CSV-file/m-p/703820#M215703</link>
      <description>&lt;P&gt;Further to your advice, I used the following:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;TERMSTR=CRLF&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;It looks like it has worked!&lt;/P&gt;
&lt;P&gt;Thanks for the swift reply.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Sat, 05 Dec 2020 09:55:39 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Find-and-replace-line-feeds-0A-x-within-a-CSV-file/m-p/703820#M215703</guid>
      <dc:creator>Norman21</dc:creator>
      <dc:date>2020-12-05T09:55:39Z</dc:date>
    </item>
  </channel>
</rss>

