我有一个预定义命令\mycommand
,由于某种原因,它输出{"/home/user/di rect ory/"/}
。 (是的,引号后面有一个斜杠,并且还有花括号。)能否想到一行或最简单的 TeX/LaTeX 代码来删除引号,可能还有花括号,以便剩下的是/home/user/di rect ory//
?
请勿加载额外的包裹。
\def\mycommand{{"/home/user/di rect ory/"/}}
\def\mycommand{{\string "/home/user/di rect ory/\string "/}}
编辑:当路径包含空格时,命令就会执行,\def\mycommand{{/home/user/directory//}}
否则会执行。仍在寻找一种优雅的方法来提取路径。
答案1
大括号
一行代码即可删除花括号:
\expandafter\def\expandafter\mycommand\mycommand
解释:
\mycommand
包含{"/home/user/di rect ory/"/}
。当\expandafter
命令完成其工作后,剩余内容如下:
\def\mycommand{"/home/user/di rect ory/"/}
花括号现在用于定义文本。
引号
另一行删除引号的方法:
\def\x"#1"{#1}\edef\mycommand{\expandafter\x\mycommand}
的结果\show\mycommand
:
> \mycommand=macro:
->/home/user/di rect ory//.
解释:
宏\x
定义为需要以引号作为分隔标记的分隔参数的宏。返回的参数不带引号。
\edef
扩展定义文本。扩展后\expandafter
:
\edef\mycommand{\x"/home/user/di rect ory/"/}
扩展后\x
:
\edef\mycommand{/home/user/di rect ory//}
然后就没有什么可扩展的了,并\edef
定义像这样的宏 \def
。
答案2
这是一个基于 LuaLaTeX 的解决方案。\DeleteQuotes
设置了一个名为的 LaTeX 宏,它删除了全部 "
"
其参数中的字符。对于的参数中的位置或字符数,没有施加或要求任何假设\DeleteQuotes
。特别是,如果 的参数根本\DeleteQuotes
不包含任何"
字符,则不会出现任何困难。(顺便说一句,只要花括号在数量和顺序上都是平衡的,TeX 就会自动将其删除。)
% !TEX TS-program = lualatex
\documentclass{article}
\usepackage{luacode}
%% Lua-side code
\begin{luacode}
function delete_quotes ( s )
s = string.gsub ( s, '"', '')
tex.sprint ( s )
end
\end{luacode}
%% TeX-side code
\newcommand\DeleteQuotes[1]{\directlua{delete_quotes(\luastring{#1})}}
\begin{document}
\newcommand\MyCommand{{"/home/user/di rect ory/"/}}
\DeleteQuotes{\MyCommand}
\end{document}
答案3
假设令牌列表的格式为
{..."..."...}
该\normalize
宏接收要规范化的标记列表作为强制参数,可能采用“存储”形式。可选参数应为将接收规范化字符串作为替换文本的控制序列(不执行关于其是否定义的检查)。如果没有给出可选参数,则强制参数应为存储字符串的控制序列,该控制序列将被重新定义。
\documentclass{article}
\makeatletter
\newcommand{\normalize}{\@dblarg\norm@lize}
\def\norm@lize[#1]#2{%
\expandafter\expandafter\expandafter
\remove@quotes
\expandafter
\@firstofone#2\remove@quotes{#1}%
}
% remove the last #3 in the following if you want to remove
% the tokens after the second quote symbol
\def\remove@quotes#1"#2"#3\remove@quotes#4{\def#4{#1#2#3}}
\makeatother
\def\mycommand{{"/home/user/di rect ory/"/}}
\normalize[\tmp]{\mycommand}\show\tmp
\normalize{\mycommand}\show\mycommand
\normalize[\another]{{"/home/user/di rect ory/"/}}\show\another
\stop
这是终端上的输出:
> \tmp=macro:
->/home/user/di rect ory//.
l.18 \normalize[\tmp]{\mycommand}\show\tmp
?
> \mycommand=macro:
->/home/user/di rect ory//.
l.20 \normalize{\mycommand}\show\mycommand
?
> \another=macro:
->/home/user/di rect ory//.
l.22 ...{"/home/user/di rect ory/"/}}\show\another
?
如果将代码\def#4{#1#2#3}
改为\def#4{#1#2}
,则结束引号后的标记将被丢弃,并且终端上的输出为
> \tmp=macro:
->/home/user/di rect ory/.
l.18 \normalize[\tmp]{\mycommand}\show\tmp
?
> \mycommand=macro:
->/home/user/di rect ory/.
l.20 \normalize{\mycommand}\show\mycommand
?
> \another=macro:
->/home/user/di rect ory/.
l.22 ...{"/home/user/di rect ory/"/}}\show\another
?
现在输入格式似乎已经完全了解了,下面针对这两种情况给出不同的解决方案。
\documentclass{article}
\makeatletter
\newcommand\extractrealpath{\@dblarg\extract@real@path}
\def\extract@real@path[#1]#2{%
% remove the braces and stringify the quotes
\edef\erp@temp{\expandafter\@firstofone#2}%
% remove the trailing slash
\expandafter\erp@remove@slash\erp@temp\@nil
\erp@remove@quotes
\let#1\erp@temp
}
\def\erp@remove@slash#1/\@nil{%
\def\erp@temp{#1}%
}
\begingroup\catcode`\"=12
\gdef\erp@remove@quotes{\expandafter\erp@remove@quotes@aux\erp@temp""\@nil}
\gdef\erp@remove@quotes@aux#1"#2"#3\@nil{%
\ifx\hfuzz#2\hfuzz
% no quotes
\def\erp@temp{#1}%
\else
\def\erp@temp{#2}%
\fi
}
\endgroup
\makeatother
\begin{document}
\def\mycommand{{\string "/home/user/di rect ory/\string "/}}
\extractrealpath[\saved]\mycommand
\texttt{\saved}
\def\mycommand{{/home/user/directory//}}
\extractrealpath\mycommand
\texttt{\mycommand}
\end{document}
答案4
我第一次玩这种东西,所以可能不对。我让每个人都可以修改这个答案,如果他愿意的话。
四行。
这是一个完全可扩展的解决方案,并且该\edef
部分用于显示两件事:第一,它是完全可扩展的;第二,以便\detokenize
显示{
和}
不在结果中。
\documentclass{scrartcl}
\def\endremovequotes{\endremovequotes}
\def\removequotes#1{\expandafter\doremovequotes#1"\endremovequotes"}
\def\doremovequotes#1{\dodoremovequotes#1}
\def\dodoremovequotes#1"{\ifx\endremovequotes#1\empty\else#1\expandafter\dodoremovequotes\fi}
\def\tmp{{"/home/user/di rect ory/"/}}
\begin{document}
\removequotes\tmp
\edef\tmp{\removequotes\tmp}
\texttt{\detokenize\expandafter{\tmp}}
\end{document}
三行字 :)
\def\removequotes#1{\expandafter\doremovequotes#1"\relax}
\def\doremovequotes#1{\dodoremovequotes#1}
\def\dodoremovequotes#1"#2\relax{\if\relax\detokenize{#2}\relax\csname @gobble\expandafter\endcsname\else\csname @firstofone\expandafter\endcsname\fi{#1\dodoremovequotes#2\relax}}
旧定义
\makeatletter
\newcommand*\removequotes[1]{\expandafter\doremovequotes#1}
\def\doremovequotes#1{\ifquotein{#1}{\removeonequote{#1}}{#1}}
\def\ifquotein#1{\doifquotein#1""\relax}
\def\doifquotein#1"#2"\relax%
{\if\relax\detokenize{#2}\relax
\expandafter\@secondoftwo\else\expandafter\@firstoftwo\fi}
\def\removeonequote#1{\doremoveonequote#1\relax}
\def\doremoveonequote#1"#2\relax{\doremovequotes{#1#2}}
\makeatother