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



我有一个csv文件,其中有用户输入的评论,偶尔以换行符结束。这会在使用infile时导致错误,并导致变量顺序错误的行。

我试过termstr=crlfcrlf。使用lfcrlf,我得到零观察值,使用cr,我得到相同的错误,如果我把它遗漏。

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

文件来自backendless,原始数据来自智能手机

编辑:我使用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)之后。

如果您的数据有正常的CRLF终止字符串,这将工作。这是用来读取在excel中创建的3列文件,并在少数地方的字符串中间输入alt+enter。

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

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

你总是可以看到什么在使用recfmt=V和查看十六进制输出。

data test2;
infile "c:tempnewlines.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"。所以找到你的第一个法线结束(看一下,找出最后一列应该是什么),看看它后面是否有0da。如果没有,那么就没有CRLF终止符,这是一个问题。

注意,当你在Excel中打开它时,Excel无疑会为你添加它们,所以这并不能帮助解决这个问题——你必须查看原始文件。

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

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

在第一行中,"More"one_answers"Stuff"之间有一个0A。[更多的是4D6F7265,东西是5374756666]。都在一行,原始CSV文件是

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

用换行代替"More Stuff"中的空格。

在第二行,"stuff"后面有0D0A(7374756666,与上面相同,但小写s是73而不是53)。这是CR+LF,法线终止符。

如果你的原始文件中没有行结束符,你可能需要用变量输入读入它。你可以有dlm=',',也可以有recfm=v,它允许你一次只读取一个分隔的位。

data test3;
 infile "c:tempnewlines.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和读取流输入是另一个很好的解决方案)。搜索谷歌/等。获取更多详细信息。

您可以尝试使用misover或truncover inffile选项,以防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;

最新更新