用于从字符串中删除字符的一行代码

用于从字符串中删除字符的一行代码

我有一个预定义命令\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

相关内容