使用SYSPARM获取SAS数据集行数:Shell脚本变量异常求助
解决通过Shell脚本调用SAS获取数据集行数的问题
我看了你的脚本,问题主要出在宏变量解析、sysparm传递的内容以及SAS输出捕获这几个地方,下面一步步给你修正:
问题分析
- 宏变量未解析:你的
set "&sysparm" nobs=nobs;用了单引号,SAS里单引号会阻止宏变量&sysparm的解析,这条语句根本没用到你传递的参数。 - sysparm传递内容错误:你已经定义了逻辑库
sasdata指向目标路径,不需要传递物理文件路径($path/$name.sas7bdat),直接传递逻辑库.数据集名即可,否则SAS会把物理路径当成临时逻辑库处理,容易出问题。 - 输出捕获冗余:默认
sas命令会输出全部日志内容,你直接把结果赋值给var,会包含大量无关日志,而不只是你要的行数。
修正后的脚本
echo -n "Enter path: " read path echo -n "Enter dataset: " read name # 生成SAS程序 cat > "$path/test1.sas" <<EOF options nofmterr nosymbolgen nomprint nomlogic; # 关闭不必要的日志输出,减少干扰 libname sasdata "$path" access=readonly; data _null_; file stdout; set sasdata.&name nobs=nobs; # 直接使用逻辑库.数据集名 put nobs; stop; # 只读取第一行就能获取nobs,不需要遍历整个数据集 run; libname sasdata clear; # 清理逻辑库 EOF # 执行SAS程序,只捕获标准输出,过滤日志 var=$(sas "$path/test1.sas" -log /dev/null -print stdout) echo "Dataset row count: [$var]"
另一种更高效的方式(不用读取数据集)
其实获取数据集行数不需要读取数据集,直接查询SAS的字典表DICTIONARY.TABLES或者PROC SQL,速度更快,尤其是大数据集:
echo -n "Enter path: " read path echo -n "Enter dataset: " read name cat > "$path/test1.sas" <<EOF options nofmterr nosymbolgen nomprint nomlogic; libname sasdata "$path" access=readonly; proc sql noprint; select nobs into :rowcount from dictionary.tables where libname='SASDATA' and memname=upcase("&name"); quit; data _null_; file stdout; put &rowcount; run; libname sasdata clear; EOF var=$(sas "$path/test1.sas" -log /dev/null -print stdout) echo "Dataset row count: [$var]"
关键优化点说明
- 用
-log /dev/null把日志输出到空设备,只保留程序的标准输出,这样var里就只有行数了。 - 关闭
symbolgen mprint mlogic这些选项,减少不必要的日志输出。 - 使用字典表的方式不需要读取数据集,对于大表来说效率提升非常明显。
- 如果一定要用sysparm传递参数,要确保传递的是逻辑库.数据集名,并且在SAS程序里用双引号包裹宏变量(比如
set "&sysparm" nobs=nobs;),同时调用SAS时用sas test1.sas -sysparm "sasdata.$name"。
内容的提问来源于stack exchange,提问作者MPUSA
相关产品推荐
相关产品推荐

