在某些字段中使用换行符读取csv,termstr = crlf不起作用

时间:2014-08-06 10:28:36

标签: sas

我有一个csv文件,其中有用户输入的注释,偶尔会以换行符结尾。这会在使用infile时导致错误,并导致行中包含错误排序的变量。

我已尝试termstr=crlfcrlf。使用lfcrlf我会读入零观察值,而使用cr,我会得到相同的错误,就像我将其删除一样。

如果我在excel中打开文件并执行替换ctrl-j(例如http://blog.contextures.com/archives/2013/05/28/find-and-replace-line-breaks-in-excel/),它会解决问题并且数据读取完美。

该文件来自后端,原始数据来自智能手机。

编辑:我使用http://support.sas.com/kb/41/116.html作为来源解决了这个问题,最后得到了以下内容

data _null_;
  infile 'test.csv' recfm=n lrecl=50000;
  file 'testout.csv' recfm=n;
  input a $char1.;
  if a = '"' then do;
    d+1;
    if d = 2 then d = 0;
  end;
  if a = "," and d = 0 then do;
    c+1;
  end;
  if a = '0A'x then do;
    if c = 2 then do;
      c = 0;
      put '0A'x;
    end;
  end;
  else put a $char1.;
run;

第一个条件跟踪我看到的分隔符(,)是真正的分隔符还是仅仅在字符串内,第二个条件计算到目前为止我看到的变量的数量。最后一个条件会删除所有lf,除非我看到了正确数量的变量(c=2)。

2 个答案:

答案 0 :(得分:1)

如果您的数据具有正常的CRLF终止字符串,这将起作用。这用于读取在3列中使用excel创建的文件,并在几个地方的字符串中间输入alt +。

data test;
  infile "c:\temp\newlines.csv" termstr=crlf dlm=',' dsd;
  format stuff stuff2 stuff3 $100.;
  input
   stuff $
   stuff2 $
   stuff3 $
  ;
run;

如果最终只有stuff有一个值(前100个字符或其他),那么您的数据中可能没有CRLF。如果它来自第三方服务(就像你的那样),我要去的第一个地方就是那个服务或应用程序,看看你有哪些选择。

您可以随时查看使用recfmt=V并查看HEX输出的内容。

data test2;
infile "c:\temp\newlines.csv" recfm=f ls=20 end=eof flowover;
format indata $20.;
do until (eof);
  input @1 indata $20.;
  put indata= hex.;
  put indata=;
end;
stop;
run;

一次为您提供20个字符,十六进制和普通的ASCII表示。 CR为“0D”,LF为“0A”。所以找到你的第一个正常的行结束[直观地看,最后一列应该是什么],然后看看它后面是否有0D0A。如果没有,那么你没有CRLF终结器,这是一个问题。

请注意,当您在Excel中打开它时,excel无疑会为您添加它们,因此无法帮助解决此问题 - 您必须查看原始文件。

例如,上面的我的垃圾数据文件为前2个输入传递生成:

indata=73747566662C224D6F72650A5374756666222C4D
indata=stuff,"More Stuff",M
indata=792073747566660D0A6F6E652C74776F2C746872
indata=y stuff  one,two,thr

在第一行中,“More”和“Stuff”之间有0A。 [更多是4D6F7265,东西是5374756666]。这一切都在一行上,原始的CSV是

stuff, "More Stuff", My stuff
one,two,three

除了换行而不是“更多东西”中的空格。

在第二行,“stuff”之后有0D0A(7374756666,与上面相同,但是小写s是73而不是53)。那是CR + LF,正常的行终止符。

如果原始文件中没有行终止符,则可能需要使用变量输入读取它。您可以dlm=','recfm=v,这样您就可以一次只读取一个分隔的位。

data test3;
 infile "c:\temp\newlines.csv" recfm=v dlm=',' dsd end=eof flowover termstr=crlf;
 format stuff stuff2 stuff3 $100.;
 input stuff $ @;
 input stuff2 $ @;
 input stuff3 $ @;
run;

使用recfm=v基本上不用担心缺少行终止符。此问题还有许多其他解决方案(recfm=n和读取流输入,例如,另一个很好的解决方案)。搜索Google等。了解更多有关您的特定问题的详细信息。

答案 1 :(得分:0)

您可以尝试使用missover或trunco​​ver infile选项,以防在缺少换行符时SAS读取超过行尾的情况导致您的错误。

您也可以在infile语句之后和输入语句之前压缩缓冲区自动变量中的换行符。例如:

data test; 
    infile "myfile.csv"; 

    * Hold the current line being read;
    input @; 

    * Compress out the LF -- you could also try this with CR and CRLF;
    _infile_ = compress(_infile_,'0A'x); 

    * Your input statement should now read the cleaned up buffer;
    input  myvar ; 
run;