为什么在应用 tranwrd 函数后最后一个字符被删除

Why is the last character getting removed after applying tranwrd function

我想替换我的 json 文件中的某些值(在此示例中,空值带有空引号。)我的解决方案工作正常,但出于某种神秘原因,[= 的最后一个字符19=] 文件被删除。无论最后一个字符如何,代码总是将其删除 - 我也尝试过使用另一个以大括号结尾的 json 文件。

是什么原因造成的,更重要的是我该如何预防?

data testdata_;
input var1 var2 var3;
format _all_ commax10.1;
datalines;
 3.1582 0.3 1.8
 21 . .
 1.2 4.5 6.4
;
proc json out = 'G:\test.json' pretty fmtnumeric nosastags keys;
export testdata_;
run;

data _null_;
  infile 'G:\test.json';
  file 'G:\test.json';
  input;
  _infile_ = tranwrd(_infile_,'null','""');
  put _infile_ ;
run;

要查看内容如何变化,首先运行代码直到“数据null”语句并检查文件内容,然后运行最后一个声明。

Data _null_ 正确;不要写入同一个文件。 SAS 提供了这个选项,但在现代,它几乎总是错误的答案,因为 SAS 如何支持这个以及存储足够便宜和快速的事实。

在这种情况下,看起来这是一个相对容易的修复,但您可能应该按照建议操作并写入一个新文件 - 还会有其他问题。

data testdata_;
input var1 var2 var3;
format _all_ commax10.1;
datalines;
 3.1582 0.3 1.8
 21 . .
 1.2 4.5 6.4
;
proc json out = 'H:\temp\test.json' pretty fmtnumeric nosastags keys;
export testdata_;
run;

data _null_;
  infile 'H:\temp\test.json' end=eof;
  file 'H:\temp\test.json';
  input @;
  putlog _infile_;
  _infile_ = tranwrd(_infile_,'null','""  ');
  
  len = length(_infile_);
  put _infile_ ;
  if eof then put _infile_;
run;

有两个变化。第一,我在 tranwrd 中使用 '"" ' 而不是 '""';那是因为否则你会在添加新行时得到稍微奇怪的结果。如果您的 JSON 解析器不喜欢 "" ,,那么您可能希望使用两个 tranwrd,一个用于 null,,一个用于 null,或其他相似(或使用正则表达式)。但重要的是输入和输出中需要匹配的字符数。如果你不能处理它(比如额外的 spaces 是有问题的)那么你只能“写一个新文件”。

第二,我寻找文件的结尾,然后故意在那里写下第二行。这避免了您在括号中遇到的问题,因为它避免了在括号之前写出 EOF。我不是 100% 确定我知道你为什么需要它 - 但你知道。

另一个可能更有意义的选项是只写有方括号的行。

data _null_;
  infile 'H:\temp\test.json' sharebuffers; 
  file 'H:\temp\test.json';
  input @;
  putlog _infile_;
  if find(_infile_,'null') then do;
    _infile_ = tranwrd(_infile_,'null','"" ');  
    put _infile_;
  end;
run;

我添加了 sharebuffers,因为这会使它 运行 快一点。请注意,我还删除了一个 space - 关于 SAS 如何执行此操作的一些奇怪的事情似乎从以下行中删除了一个 space 否则。不知道为什么,可能是 EOL 字符有些奇怪。

但再次强调 - 除非没有其他选择,否则不要执行任何操作。写一个新文件。

一个奇怪的事情是 PROC JSON 总是写入一个使用 LF 作为行尾字符的文本文件。

因此,如果添加以下注意事项,您可能能够覆盖文件:

  1. 在 INFILE 语句中使用 TERMSTR=LF。
  2. 在 INFILE 语句上使用 SHAREDBUFFERS。
  3. 用 TRANWRD() 函数替换相同字节数的字符串,并且不要将 space 作为该行的最后一个字符。

我还会搜索“: null”而不仅仅是 'null' 以降低替换文件中其他字符串中的这些字符的风险。

data _null_;
  infile json SHAREBUFFERS termstr=lf ;
  file json ;
  input ;
  _infile_ = tranwrd(_infile_,': null',':   ""');
  put _infile_;
run;