使用 xparse 访问 sqlite3 (在 XeLaTeX 下)

使用 xparse 访问 sqlite3 (在 XeLaTeX 下)

当我读到egreg 的 2019 年附录关于如何从 LaTeX 启动 shell 脚本并获取输出。

但是当我尝试使用它连接 SQLite 数据库时,出现了 LaTeX3 错误。以下是(最小)代码:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\captureshell}{som}
 {
  \sdaau_captureshell:Ne \l__sdaau_captureshell_out_tl { #3 }
  \IfBooleanT { #1 }
   {% we may need to stringify the result
    \tl_set:Nx \l__sdaau_captureshell_out_tl
     { \tl_to_str:N \l__sdaau_captureshell_out_tl }
   }
  \IfNoValueTF { #2 }
   {
    \tl_use:N \l__sdaau_captureshell_out_tl
   }
   {
    \tl_set_eq:NN #2 \l__sdaau_captureshell_out_tl
   }
 }

\tl_new:N \l__sdaau_captureshell_out_tl

\cs_new_protected:Nn \sdaau_captureshell:Nn
 {
  \sys_get_shell:nnN { #2 } { } #1
  \tl_trim_spaces:N #1 % remove leading and trailing spaces
 }
\cs_generate_variant:Nn \sdaau_captureshell:Nn { Ne }
\ExplSyntaxOff

\begin{document}

\captureshell{sqlite3 /hom/yannis/texmf/yannis.db 'select title from title where id="grafematik2020/hara/hara.tex"'}

\end{document}

错误说我不允许在 shell 命令中使用双引号:

! LaTeX3 Error: Quotes in shell command 'sqlite3 /hom/yannis/texmf/yannis.db
(LaTeX3)        'select title from title where
(LaTeX3)        id="grafematik2020/hara/hara.tex"''.

For immediate help type H <return>.
 ...                                              
                                                  
l.34 ... where id="grafematik2020/hara/hara.tex"'}
                                                  
? H

Shell commands cannot contain quotes (").

如何在 shell 命令行中将字符串嵌套在 SQL 命令中,而不使用双引号?

写出不使用引号的参数值id违反了 SQL 语法:它会将其视为列名...

[PS:不,我不想使用 LuaTeX 或 Context,尽管我知道它们更适合与 sqlite3 对话。]

答案1

您不能"在 shell 命令中(直接)使用双引号(ASCII 34),原因与您不能在 web2c TeX 实现(TeX Live、MiKTeX 等)中的文件名中使用双引号的原因相同。


Shell 转义是作为伪文件实现的,因此您使用 I/O 原语(\openin、、)与 shell 交互,因此所有文件名限制都适用于 shell 命令\write\input


Knuth 最初的 TeX 实现不允许在文件名中使用空格(为了更好的理解 :),因为它使用空格作为文件名的终止符。如果您使用原始语法\input(在 LaTeX 中是\@@input),您仍然可以看到该实现:

\input my_file.tex text after

上面这一行将输入my_file.tex,执行其中的任何操作,然后排版text after

为了允许在文件名中使用空格,2004 年 Olaf W 在 TeX 中实现了带引号的文件名作为文件系统相关的更改(从而影响了 Knuth TeX),因此您可以输入:

\input "file with spaces.tex" text after

但实现还允许您输入

\input file" "with" "spaces.tex text after

它将删除全部引号,同时保留奇数个引号后的空格。

该实现的问题是,无论如何(即使使用大括号文件名语法),引号都会从文件名中删除,因此目前无法在文件名的任何地方使用引号(因此不能在 shell 命令的任何地方使用引号: expl3只会阻止您使用该命令,因为如果没有引号,它可能无法按您预期的方式工作)。


也就是说,该限制适用于 TeX 内部处理的文件名。David 的建议应该可以正常工作,因为引号不经过 TeX 的文件名解析:

\newwrite\tmp
\openout\tmp{tmp.sh}
\immediate\write\tmp{ls "/some/path/with spaces/"}
\closeout\tmp

\input{|bash tmp.sh} % \input{"|bash tmp.sh"} if in LaTeX, or your own \captureshell command

相关内容