我正在为学生准备一份 LaTeX 投影仪演示文稿。我正在寻找一种简单的方法来创建两个版本的演示文稿。
一个版本是给学生的,其中只包含他们家庭作业的任务文本;另一个版本是给我的,其中还包含解决方案。
因此我创建了一个宏,用于检查文件名是否包含“student”。如果包含,则宏不输出任何内容,如果不包含,则传递参数:
\newcommand{\hausaufgabenLoesung}[1]{%
\IfSubStringInString{student}{\jobname}{}{#1}%
}
但这并没有按预期工作。无论我如何命名文件,条件总是转到 false 表达式。我认为宏\jobname
返回了一些无法处理的内容\IfSubStringInString
,但我不知道该如何处理这个问题。
如果我\jobname
用固定字符串替换条件中的宏,它会按预期工作,但这会使其变得毫无用处。
我过去常常\jobname
避免包含 currfile-package,但使用 currfile-macros 时,我得到了相同的行为。我在 Linux 和 Windows 上使用 texlive 2014 pdflatex。
这里有谁对此有提示吗?
这是一个最小的完整示例:
\documentclass[ngerman]{beamer}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage[ngerman]{babel}
\usepackage{ifthen}
\usepackage{substr}
\newcommand{\hausaufgabenLoesung}[1]{%
\IfSubStringInString{student}{\jobname}{}{#1}%
}
\begin{document}
\begin{frame}{Title}{Subtitle}
\begin{itemize}
\item \jobname
\item Visible in both files
\hausaufgabenLoesung{\item Solution not in the student file}
\end{itemize}
\end{frame}
\end{document}
答案1
中的字符\jobname
有类别代码 12,这违反了substr
使用\ifx
基于比较的 。您可以简单地将 字符串化student
,因为substr
命令会完全展开其参数:
\documentclass[ngerman]{beamer}
\usepackage[T1]{fontenc}
\usepackage[ngerman]{babel}
\usepackage{substr}
\newcommand{\hausaufgabenLoesung}[1]{%
\IfSubStringInString{\detokenize{student}}{\jobname}{}{#1}%
}
\begin{document}
\begin{frame}{Title}{Subtitle}
\begin{itemize}
\item \jobname
\item Visible in both files
\hausaufgabenLoesung{\item Solution not in the student file}
\end{itemize}
\end{frame}
\end{document}
如果文件名不包含以下内容,我将获得以下结果student
:
如果文件名包含以下内容,我将获得以下结果student
:
一个经典的解决方案(没有\detokenize
):
\documentclass[ngerman]{beamer}
\usepackage[T1]{fontenc}
\usepackage[ngerman]{babel}
\usepackage{substr}
\begingroup\escapechar=-1
\xdef\studentstring{\string\student}
\endgroup
\newcommand{\hausaufgabenLoesung}[1]{%
\IfSubStringInString{\studentstring}}{\jobname}{}{#1}%
}
\begin{document}
\begin{frame}{Title}{Subtitle}
\begin{itemize}
\item \jobname
\item Visible in both files
\hausaufgabenLoesung{\item Solution not in the student file}
\end{itemize}
\end{frame}
\end{document}
使用正则表达式的解决方案(具有广泛的通用性):
\documentclass[ngerman]{beamer}
\usepackage[T1]{fontenc}
\usepackage[ngerman]{babel}
\ExplSyntaxOn
\NewDocumentCommand{\hausaufgabenLoesung}{m}
{
\regex_match:nVF {student} \c_sys_jobname_str {#1}
}
\cs_generate_variant:Nn \regex_match:nnF { nV }
\ExplSyntaxOff
\begin{document}
\begin{frame}{Title}{Subtitle}
\begin{itemize}
\item \jobname
\item Visible in both files
\hausaufgabenLoesung{\item Solution not in the student file}
\end{itemize}
\end{frame}
\end{document}
答案2
根据 Ulrike Fischer 的评论,\jobname
其中包含“错误”的 catcode 字符,使用某些 hack 无法进行直接比较。一种解决方法是将作业名称写入虚拟文件,然后立即将其读回某个\def\....
宏,例如\RealJobName
。这可以用作测试的一个字符串占位符。
环境\AtBeginDocument{}
钩子会自动执行此操作并“返回”作业名称\RealJobName
以供日后使用。
两种方法均substr
有效xstring
。
学生姓名.tex
\documentclass[ngerman]{beamer}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage[ngerman]{babel}%
\usepackage{ifthen}
\usepackage{substr}
\usepackage{xstring}%
\newcommand{\hausaufgabenLoesung}[1]{%
\IfSubStringInString{student}{\RealJobName}{}{#1}%
}
\newcommand{\hausaufgabenLoesungXString}[1]{%
\IfSubStr{\RealJobName}{student}{}{#1}%
}
\gdef\RealJobName{}%
\newwrite\mywrite%
\newread\myread%
\AtBeginDocument{%
\immediate\openout\mywrite\jobname.dum%
\immediate\write\mywrite{\jobname}%
\immediate\closeout\mywrite%
\immediate\openin\myread=\jobname.dum%
\read\myread to \RealJobName%
\immediate\closein\myread%
}%
\begin{document}
\begin{frame}{Title}{Subtitle}
\begin{itemize}
\item \jobname
\item Visible in both files
\hausaufgabenLoesung{\item Solution not in the student file}
\hausaufgabenLoesungXString{\item Solution not in the student file}
\end{itemize}
\end{frame}
\end{document}