本程序用于从 .sas 文件中提取需要递交至监管机构的代码,并另存为 .txt 格式的文件。
然后使用 pip 命令安装指定版本,例如:
pip install git+https://github.com/smjc-org/py-submit.git@0.5.4或者从特定 commit 安装:
pip install git+https://github.com/smjc-org/py-submit.git@3c98b34901ca0a70c50c0ef559d1ebb920ce9757上述命令会将本程序安装到环境变量中指定的目录下,后续可直接通过 submit 命令调用。
Note
对于 Windows 用户,你可以在 %LOCALAPPDATA%/Programs/Python/Python313/Scripts 中看到 submit.exe,你在终端执行 submit 命令实际上调用的是这个程序。
submit 命令会识别 .sas 文件中的特殊注释,根据这些注释,删除多余的代码片段,保留需要递交的代码片段。
submit 命令可以识别的特殊注释如下:
/*symbolsSUBMIT BEGINsymbols*/: 指定需要提交的代码的起始位置/*symbolsSUBMIT ENDsymbols*/: 指定需要提交的代码的终止位置/*symbolsNOT SUBMIT BEGINsymbols*/: 指定无需提交的代码的起始位置/*symbolsNOT SUBMIT ENDsymbols*/: 指定无需提交的代码的终止位置
Note
symbols可以是符号*,-,=,(空格) 的任意组合- 注释不区分大小写
举例:
/*
Top-Level Comment
*/
proc datasets library = work memtype = data kill noprint;
quit;
dm ' log; clear; output; clear; odsresult; clear; ';
/*SUBMIT BEGIN*/
proc sql noprint;
create table work.adsl as select * from rawdata.adsl;
quit;
proc sql noprint;
create table work.t_6_1_1 as select * from adsl;
quit;
/*SUBMIT END*/
%LOG;
%ERROR;经 submit 命令处理之后将会变成:
proc sql noprint;
create table work.adsl as select * from rawdata.adsl;
quit;
proc sql noprint;
create table work.t_6_1_1 as select * from adsl;
quit;子命令 copyfile 用于处理单个 .sas 文件。
submit copyfile "adae.sas" "adae.txt"
submit cpf "adae.sas" "adae.txt"其中,adae.sas 是需要处理的 .sas 文件路径,adae.txt 是处理后保存的 .txt 文件路径。
Tip
cpf是copyfile的别名(alias),大多数选项都具有别名,可通过--help命令查看。- 可以使用相对路径和绝对路径,使用相对路径时,以
submit命令执行所在目录为根。 例如:在/code目录下处理子目录/code/adam中的adae.sas文件,应该执行submit copyfile "adam/adae.sas" "submit/adae.txt",此时adae.txt文件将保存在/code/submit目录下。
--convert-mode 选项用于指定处理模式,可选值为:positive, negative, both,默认为 both。
positive: 仅处理/* SUBMIT BEGIN */,/* SUBMIT END */negative: 仅处理/* NOT SUBMIT BEGIN*/,/* NOT SUBMIT END */both: 同时处理所有四个特殊注释
Important
/* NOT SUBMIT BEGIN*/, /* NOT SUBMIT END */ 的处理优先级高于 /* SUBMIT BEGIN */, /* SUBMIT END */。
submit copyfile --convert-mode negative上述命令将会把:
%macro BAplot(indata, var, outdata);
data _tmp1;
set &indata;
run;
proc sql noprint;
create table _tmp2 as select * from _tmp1;
quit;
data &outdata;
set _tmp2;
run;
/*NOT SUBMIT BEGIN*/
proc template;
define statgraph BAplot;
begingraph;
entrytitle "BA Plot";
layout overlay;
scatterplot x=Period y=BA / group=Subject;
endlayout;
endgraph;
end;
run;
proc sgrender data=&outdata template=BAplot;
run;
/*NOT SUBMIT END*/
%mend BAplot;处理为:
%macro BAplot(indata, var, outdata);
data _tmp1;
set &indata;
run;
proc sql noprint;
create table _tmp2 as select * from _tmp1;
quit;
data &outdata;
set _tmp2;
run;
%mend BAplot;--macro-subs 选项用于替换 .sas 文件中宏变量,它应当是一个字典,形式为 {key=value,...},其键 key 为宏变量名称,值 value 为替换字符串。
例如,如果想将下面的代码块中的宏变量 &id 替换为 01:
/*submit begin*/
data adeff;
set adeff.adeff&id;
run;
/*submit end*/你需要指定 --macro-subs "{id=01}"。
Tip
value 可以为空,例如 --macro-subs "{id=}",此时程序将会删除宏变量 &id。
Warning
--macro-subs 不支持嵌套的宏变量,例如:&&id,&&&id 等。
--encoding 选项指定 .sas 文件的编码格式。若未指定该选项,将尝试猜测最有可能的编码格式,并用于后续处理。
submit copyfile --convert-mode negative --encoding gbkNote
本程序使用 chardet 进行编码格式的自动识别,但 chardet 会将 gbk 编码的文件错误地识别为 gb2312 编码。chardet/chardet#168
如果出现类似 UnicodeDecodeError:'gb2312'codec can't decode byte xfb in position 6436: illegal multibyte sequence 的错误提示,请尝试手动指定 --encoding gbk。
子命令 copydir 用于处理包含 .sas 文件的目录,该命令将以递归的方式自动查找扩展名为 .sas 的文件并进行处理,非 .sas 文件将被忽略。
submit copydir "/source" "/dest"--merge 选项指定将所有 .sas 文件进行转换后合并到单个 .txt 文件。
例如:
submit copydir "/source" "/dest" --merge "code.txt"上述代码会将 /source 目录中的所有 .sas 文件转换成 .txt 文件,并将转换后的 .txt 文件合并到 /dest/code.txt 中。
Note
合并后的 .txt 文件包含源目录中所有需要递交的 sas 代码,使用注释 /*======filename.txt======*/ 分隔来自不同 .sas 文件的代码。
其中 filename 是源目录中 .sas 文件名称(不含扩展名)。
Important
某些地方医疗器械监督管理局不接收压缩包作为递交文件,且递交文件数量存在限制,因此必须将所有 .sas 文件合并成一个单独的 .txt 文件。
--exclude-dirs 选项指定排除的目录列表,这些目录中的文件将会被跳过处理。该选项支持 glob 模式,详见 glob 模式介绍。
submit copydir "/source" "/dest" --exclude-dirs macro可同时指定多个目录:
submit copydir "/source" "/dest" --exclude-dirs macro qc initial上述命令将在目录名称匹配 macro, qc 或 initial 时跳过处理其中的文件。
--exclude-files 选项指定排除的文件列表,这些文件将会被跳过处理。该选项支持 glob 模式,详见 glob 模式介绍。
submit copydir "/source" "/dest" --exclude-dirs macro --exclude-files fcmp.sas format.sas上述命令将在目录名称匹配 macro 时跳过处理其中的文件,并在文件名称匹配 fcmp.sas 或 format.sas (无论是否在 macro 目录中)时跳过处理。
glob 是一种使用通配符指定文件(目录)名称集合的模式,查看 wiki。
你可以在路径中使用以下特殊字符作为通配符:
*: 匹配任意数量的非分隔符型字符,包括零个。例如,f*.sas匹配f1.sas、f2.sas、f3.sas等等。**: 匹配任意数量的文件或目录分段,包括零个。例如,**/f*.sas匹配figure/f1.sas、figure/f2.sas、figure/draft/f1.sas等等。?: 匹配一个不是分隔符的字符。例如,t1?.sas匹配t1.sas、t10.sas、t11.sas等等。[seq]: 匹配在 seq 中的一个字符。例如,[tfl]1.sas匹配t1.sas、f1.sas、l1.sas。
更多语法请查看 模式语言。
假设有这样一个文件目录结构:
D:.
├─source
│ ├─f1.sas
│ ├─f2.sas
│ ├─f2-deprecated.sas
│ ├─f3.sas
│ ├─f3-deprecated.sas
│ ├─t1.sas
│ ├─t2.sas
│ ├─t2-deprecated.sas
│ ├─t2-deprecated-20241221.sas
│ ├─t3.sas
│ ├─t4.sas
│ ├─t5.sas
│ ├─t5-deprecated.sas
│ ├─t6.sas
│ ├─t7.sas
│ └─t7-deprecated.sas
└─dest
现在需要将 source 目录中的 .sas 文件转换为 .txt 文件,但忽略名称包含 deprecated 的文件。
如果不使用 glob 模式,命令应该是这样的:
submit copydir source dest --exclude-files "f2-deprecated.sas" "f3-deprecated.sas" "t2-deprecated.sas" "t2-deprecated-20241221.sas" "t5-deprecated.sas" "t7-deprecated.sas"使用 glob 模式,命令得到简化:
submit copydir source dest --exclude-files "*deprecated*.sas"usage: submit [options] copyfile [-h] [-c {positive,negative,both}] [--macro-subs MACRO_SUBS] [--encoding ENCODING] sas_file txt_file
positional arguments:
sas_file SAS 文件路径
txt_file TXT 文件路径
options:
-h, --help show this help message and exit
-c, --convert-mode {positive,negative,both}
转换模式(默认 both)
--macro-subs MACRO_SUBS
宏变量替换,格式为 {key=value,...}(默认无)
--encoding ENCODING 编码格式(默认自动检测)usage: submit [options] copydir [-h] [-c {positive,negative,both}] [--macro-subs MACRO_SUBS] [--encoding ENCODING] [-mrg MERGE] [-exf [EXCLUDE_FILES ...]] [-exd [EXCLUDE_DIRS ...]] sas_dir txt_dir
positional arguments:
sas_dir SAS 文件目录
txt_dir TXT 文件目录
options:
-h, --help show this help message and exit
-c, --convert-mode {positive,negative,both}
转换模式(默认 both)
--macro-subs MACRO_SUBS
宏变量替换,格式为 {key=value,...}(默认无)
--encoding ENCODING 编码格式(默认自动检测)
-mrg, --merge MERGE 合并到一个文件(默认无)
-exf, --exclude-files [EXCLUDE_FILES ...]
排除文件列表(默认无)
-exd, --exclude-dirs [EXCLUDE_DIRS ...]
排除目录列表(默认无).bat 文件是一种批处理文件,你可以将多条 submit 命令保存在单个 .bat 文件中,这样只需双击这个文件即可批量处理 .sas 文件。
例如:
submit copydir "D:/project/code/adam" "D:/project/submit/adam"
submit copydir "D:/project/code/tfl" "D:/project/submit/tfl" --exclude-files merge.sas
submit copydir "D:/project/code/macro" "D:/project/submit/macro" --convert-mode negative前置条件:
-
克隆仓库代码
git clone https://github.com/smjc-org/py-submit.git
-
安装依赖
uv sync
-
安装 pre-commit
pre-commit install pre-commit install --hook-type commit-msg
-
修改代码
-
测试代码
pytest
Note
执行 pytest 命令前需要先激活虚拟环境。
- 发起 pull request
Note
- 推荐使用 VSCode 编辑代码
- 需要使用 Conventional Commits 1.0.0 规范的提交信息