我有一个csv文件,其中有用户输入的评论,偶尔以换行符结束。这会在使用infile
时导致错误,并导致变量顺序错误的行。
我试过termstr=crlf
或cr
或lf
。使用lf
或crlf
,我得到零观察值,使用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;