防止 SAS 自动删除字符串中的尾随空白
Prevent SAS to automatically remove trailing blank in string
我有如下示例数据集。
data d01;
infile datalines dlm='#';
input Name & . IdNumber & . Salary & . Site & .;
datalines;
アイ# 2355# 21163# BR1
アイウエオ# 5889# 20976# BR1
カキクケ# 3878# 19571# BR2
;
data _null_ ;
set d01 ;
file "/folders/myfolders/test.csv" lrecl=1000 ;
length filler ;
filler = ' ';
w_out = ksubstr(Name, 1, 5) || IdNumber || Salary || Site || filler;
put w_out;
run ;
我想将此数据集导出为 csv(固定宽度格式),每行的长度为 20 字节(20 个 1 字节字符)。
但是 SAS 自动删除了我的尾随空格。所以结果将是每行 17 个字节。 (填充被截断)
我知道我可以像这样插入填充物。
put w_out filler .;
但是如果“站点”列为空,这将不起作用,SAS 将截断其列并且结果也不是每行 20 个字节。
默认情况下,SAS 在 FILE
语句上设置选项 NOPAD
,它还将每行设置为 'variable format',这意味着行的长度可以根据写入的数据而变化.要明确要求 SAS 用空格填充您的记录,请不要使用填充变量,只需:
- 将
LRECL
设置为您需要的文件宽度(20)
- 设置
PAD
选项,或设置RECFM=F
示例代码:
data _null_ ;
set d01 ;
file "/folders/myfolders/test.csv" lrecl=20 PAD;
w_out = Name || IdNumber || Salary || Site;
put w_out;
run ;
我不太明白你想用 ksubstr 做什么,但如果你想添加填充以使总长度达到 20 个字符,你可能需要编写一些额外的逻辑:
data _null_ ;
set d01 ;
file "/folders/myfolders/test.csv" lrecl=1000 ;
length filler ;
w_out = ksubstr(Name,1,5) || IdNumber || Salary || Site;
len = 20 - klength(w_out) - 1;
put w_out @;
if len > 0 then do;
filler = repeat(" ", len);
put filler $varying20. len;
end;
else put;
run ;
您可能不想使用多字节字符集编写固定列文件。相反,看看你是否可以调整你的过程来使用分隔文件。就像您在示例输入数据中所做的那样。
如果您希望 PUT 函数写入特定数量的字节,只需使用格式化的 PUT 语句。要使写入的字节数根据字符串值而变化,您可以使用 $VARYING 格式。使用 $VARYING 时的语法与使用普通格式时的语法略有不同。在包含要写入的实际字节数的格式规范之后添加第二个变量引用。
您可以使用 LENGTH() 函数来计算名称值占用的字节数。因为它通常会忽略尾随 space 只需在末尾添加另一个字符并从总长度中减去一个字符。
要用三个空格填充末尾,您只需在最后一个变量的格式中使用的宽度上加三个。
data d01;
infile datalines dlm='#';
length Name IdNumber Salary Site ;
input Name -- Site;
datalines;
アイ# 2355# 21163# BR1
アイウエオ# 5889# 20976# BR1
カキクケ# 3878# 19571# BR2
Sam#1#2#3
;
filename out temp;
data _null_;
set d01;
file out;
nbytes=length(ksubstr(name,1,5)||'#')-1;
put name $varying15. nbytes IdNumber . Salary . Site . ;
run;
结果:
67 data _null_ ;
68 infile out;
69 input ;
70 list;
71 run;
NOTE: The infile OUT is:
Filename=...\#LN00059,
RECFM=V,LRECL=32767,File Size (bytes)=110,
Last Modified=15Aug2019:09:01:44,
Create Time=15Aug2019:09:01:44
RULE: ----+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0
1 アイ 235521163BR1 24
2 アイウエオ588920976BR1 30
3 カキクケ 387819571BR2 28
4 Sam 1 2 3 20
NOTE: 4 records were read from the infile OUT.
The minimum record length was 20.
The maximum record length was 30.
我有如下示例数据集。
data d01;
infile datalines dlm='#';
input Name & . IdNumber & . Salary & . Site & .;
datalines;
アイ# 2355# 21163# BR1
アイウエオ# 5889# 20976# BR1
カキクケ# 3878# 19571# BR2
;
data _null_ ;
set d01 ;
file "/folders/myfolders/test.csv" lrecl=1000 ;
length filler ;
filler = ' ';
w_out = ksubstr(Name, 1, 5) || IdNumber || Salary || Site || filler;
put w_out;
run ;
我想将此数据集导出为 csv(固定宽度格式),每行的长度为 20 字节(20 个 1 字节字符)。
但是 SAS 自动删除了我的尾随空格。所以结果将是每行 17 个字节。 (填充被截断)
我知道我可以像这样插入填充物。
put w_out filler .;
但是如果“站点”列为空,这将不起作用,SAS 将截断其列并且结果也不是每行 20 个字节。
默认情况下,SAS 在 FILE
语句上设置选项 NOPAD
,它还将每行设置为 'variable format',这意味着行的长度可以根据写入的数据而变化.要明确要求 SAS 用空格填充您的记录,请不要使用填充变量,只需:
- 将
LRECL
设置为您需要的文件宽度(20) - 设置
PAD
选项,或设置RECFM=F
示例代码:
data _null_ ;
set d01 ;
file "/folders/myfolders/test.csv" lrecl=20 PAD;
w_out = Name || IdNumber || Salary || Site;
put w_out;
run ;
我不太明白你想用 ksubstr 做什么,但如果你想添加填充以使总长度达到 20 个字符,你可能需要编写一些额外的逻辑:
data _null_ ;
set d01 ;
file "/folders/myfolders/test.csv" lrecl=1000 ;
length filler ;
w_out = ksubstr(Name,1,5) || IdNumber || Salary || Site;
len = 20 - klength(w_out) - 1;
put w_out @;
if len > 0 then do;
filler = repeat(" ", len);
put filler $varying20. len;
end;
else put;
run ;
您可能不想使用多字节字符集编写固定列文件。相反,看看你是否可以调整你的过程来使用分隔文件。就像您在示例输入数据中所做的那样。
如果您希望 PUT 函数写入特定数量的字节,只需使用格式化的 PUT 语句。要使写入的字节数根据字符串值而变化,您可以使用 $VARYING 格式。使用 $VARYING 时的语法与使用普通格式时的语法略有不同。在包含要写入的实际字节数的格式规范之后添加第二个变量引用。
您可以使用 LENGTH() 函数来计算名称值占用的字节数。因为它通常会忽略尾随 space 只需在末尾添加另一个字符并从总长度中减去一个字符。
要用三个空格填充末尾,您只需在最后一个变量的格式中使用的宽度上加三个。
data d01;
infile datalines dlm='#';
length Name IdNumber Salary Site ;
input Name -- Site;
datalines;
アイ# 2355# 21163# BR1
アイウエオ# 5889# 20976# BR1
カキクケ# 3878# 19571# BR2
Sam#1#2#3
;
filename out temp;
data _null_;
set d01;
file out;
nbytes=length(ksubstr(name,1,5)||'#')-1;
put name $varying15. nbytes IdNumber . Salary . Site . ;
run;
结果:
67 data _null_ ;
68 infile out;
69 input ;
70 list;
71 run;
NOTE: The infile OUT is:
Filename=...\#LN00059,
RECFM=V,LRECL=32767,File Size (bytes)=110,
Last Modified=15Aug2019:09:01:44,
Create Time=15Aug2019:09:01:44
RULE: ----+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0
1 アイ 235521163BR1 24
2 アイウエオ588920976BR1 30
3 カキクケ 387819571BR2 28
4 Sam 1 2 3 20
NOTE: 4 records were read from the infile OUT.
The minimum record length was 20.
The maximum record length was 30.