我有一个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/),它会解决问题并且数据读取完美。
该文件来自后端,原始数据来自智能手机。
编辑:我使用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
)。
答案 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或truncover 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;