\includegraphics: ファイル名に番号記号 # を含める

\includegraphics: ファイル名に番号記号 # を含める

ファイル名に「#」を含む図が何百個もあり、 を使って含めたいのですが、や\includegraphicsなどのパッケージを試しましたが、どれも機能しません。何百ものファイル名を変更する必要がないような実際の解決策を提案してもらえませんか? よろしくお願いします。grffilecurrfile

更新: 1. Windows を使用しています。 2. コンパイルすると、「定義内のパラメータ番号が不正です」と表示されます

答え1

#使用する前にcatcode を変更することができます:

\documentclass[]{article}
\usepackage{graphicx}


\begin{document}
{\catcode`\#=12 \includegraphics{test#abc}}
\end{document}

しかし、そのような名前は避けたほうがよいでしょう。

答え2

マクロ内で扱いにくい可能性がある catcode の変更の代替手段:

\documentclass{article}
\usepackage{graphicx}

\begin{document}

\includegraphics{a\string##b.png}

\end{document}

答え3

カテゴリコードを変更するには、答えUlrike Fischer のハッシュ。または、ハッシュをマクロ内に隠すこともできます。

\edef\hash{\string#}

\hash数字などの文字のカテゴリコード (12/その他) を持つハッシュに展開されるマクロとして定義されます。

例:

\documentclass{article}
\usepackage{graphicx}
% \usepackage{grffile}

\newcommand*{\hash}{}% print error message if \hash is already defined
\edef\hash{\string#}

\begin{document}
  \includegraphics[width=.5\linewidth]{test\hash abc}% "test#abc"
\end{document}

答え4

この問題は、graphics/graphicx パッケージのファイル名の処理/解析が原因です。

引数として指定されたファイル名は、\includegraphics一時マクロの定義テキストに渡されます。

これらの一時マクロが展開されると、連続するハッシュの量は半分になり、引数を示す 1..9 の範囲の数字の前にあるマーカーとして単一のハッシュが使用されるようになります。

\toks@{..}...\edef..{..\the\toks@..}これはおそらくまたは を介し​​て解決できたはずです\edef...{\unexpanded{..}..}

\detokenizeeTeX 拡張機能の -primitive が使用可能な場合は、トークンがカテゴリ コード 6 (パラメータ) の明示的な文字トークンであるかどうかのチェックを実装できます。

したがって、eTeX 拡張機能の -primitive が利用可能な場合\detokenize、ファイル名内のすべてのハッシュ (カテゴリ コード 6 のすべての明示的な文字トークン) をその文字列化/カテゴリ コード 12 ペンダントで再帰的に置き換えるルーチンを実装できます。

% This example uses \detokenize and thus requires eTeX extensions.

\documentclass{article}
\usepackage{graphicx}

\makeatletter
%%=============================================================================
%% Paraphernalia:
%%    \UD@firstoftwo, \UD@secondoftwo,
%%    \UD@PassFirstToSecond, \UD@Exchange, \UD@removespace
%%    \UD@CheckWhetherNull, \UD@CheckWhetherBrace,
%%    \UD@CheckWhetherLeadingSpace, \UD@ExtractFirstArg
%%=============================================================================
\newcommand\UD@firstoftwo[2]{#1}%
\newcommand\UD@secondoftwo[2]{#2}%
\newcommand\UD@PassFirstToSecond[2]{#2{#1}}%
\newcommand\UD@Exchange[2]{#2#1}%
\newcommand\UD@removespace{}\UD@firstoftwo{\def\UD@removespace}{} {}%
%%-----------------------------------------------------------------------------
%% Check whether argument is empty:
%%.............................................................................
%% \UD@CheckWhetherNull{<Argument which is to be checked>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is empty>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
\newcommand\UD@CheckWhetherNull[1]{%
  \romannumeral0\expandafter\UD@secondoftwo\string{\expandafter
  \UD@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
  \UD@secondoftwo\string}\expandafter\UD@firstoftwo\expandafter{\expandafter
  \UD@secondoftwo\string}\expandafter\expandafter\UD@firstoftwo{ }{}%
  \UD@secondoftwo}{\expandafter\expandafter\UD@firstoftwo{ }{}\UD@firstoftwo}%
}%
%%-----------------------------------------------------------------------------
%% Check whether argument's first token is a catcode-1-character
%%.............................................................................
%% \UD@CheckWhetherBrace{<Argument which is to be checked>}%
%%                      {<Tokens to be delivered in case that argument
%%                        which is to be checked has leading
%%                        catcode-1-token>}%
%%                      {<Tokens to be delivered in case that argument
%%                        which is to be checked has no leading
%%                        catcode-1-token>}%
\newcommand\UD@CheckWhetherBrace[1]{%
  \romannumeral0\expandafter\UD@secondoftwo\expandafter{\expandafter{%
  \string#1.}\expandafter\UD@firstoftwo\expandafter{\expandafter
  \UD@secondoftwo\string}\expandafter\expandafter\UD@firstoftwo{ }{}%
  \UD@firstoftwo}{\expandafter\expandafter\UD@firstoftwo{ }{}\UD@secondoftwo}%
}%
%%-----------------------------------------------------------------------------
%% Check whether brace-balanced argument starts with a space-token
%%.............................................................................
%% \UD@CheckWhetherLeadingSpace{<Argument which is to be checked>}%
%%                             {<Tokens to be delivered in case <argument
%%                               which is to be checked>'s 1st token is a
%%                               space-token>}%
%%                             {<Tokens to be delivered in case <argument
%%                               which is to be checked>'s 1st token is not
%%                               a space-token>}%
\newcommand\UD@CheckWhetherLeadingSpace[1]{%
  \romannumeral0\UD@CheckWhetherNull{#1}%
  {\expandafter\expandafter\UD@firstoftwo{ }{}\UD@secondoftwo}%
  {\expandafter\UD@secondoftwo\string{\UD@CheckWhetherLeadingSpaceB.#1 }{}}%
}%
\newcommand\UD@CheckWhetherLeadingSpaceB{}%
\long\def\UD@CheckWhetherLeadingSpaceB#1 {%
  \expandafter\UD@CheckWhetherNull\expandafter{\UD@secondoftwo#1{}}%
  {\UD@Exchange{\UD@firstoftwo}}{\UD@Exchange{\UD@secondoftwo}}%
  {\UD@Exchange{ }{\expandafter\expandafter\expandafter\expandafter
   \expandafter\expandafter\expandafter}\expandafter\expandafter
   \expandafter}\expandafter\UD@secondoftwo\expandafter{\string}%
}%
%%-----------------------------------------------------------------------------
%% Extract first inner undelimited argument:
%%
%%   \UD@ExtractFirstArg{ABCDE} yields  {A}
%%
%%   \UD@ExtractFirstArg{{AB}CDE} yields  {AB}
%%.............................................................................
\newcommand\UD@RemoveTillUD@SelDOm{}%
\long\def\UD@RemoveTillUD@SelDOm#1#2\UD@SelDOm{{#1}}%
\newcommand\UD@ExtractFirstArg[1]{%
  \romannumeral0%
  \UD@ExtractFirstArgLoop{#1\UD@SelDOm}%
}%
\newcommand\UD@ExtractFirstArgLoop[1]{%
  \expandafter\UD@CheckWhetherNull\expandafter{\UD@firstoftwo{}#1}%
  { #1}%
  {\expandafter\UD@ExtractFirstArgLoop\expandafter{\UD@RemoveTillUD@SelDOm#1}}%
}%
%%=============================================================================
%% \ReplaceEveryHash{<argument>}%
%%
%%   Each explicit catcode-6(parameter)-character-token of the <argument> 
%%   will be replaced by its stringification.
%%
%%   You obtain the result after two expansion-steps, i.e., 
%%   in expansion-contexts you get the result after "hitting" 
%%   \ReplaceEveryHash by two \expandafter.
%%   
%%   As a side-effect, the routine does replace matching pairs of explicit
%%   character tokens of catcode 1 and 2 by matching pairs of curly braces
%%   of catcode 1 and 2.
%%   I suppose this won't be a problem in most situations as usually the
%%   curly braces are the only characters of category code 1 / 2...
%%
%%   This routine needs \detokenize from the eTeX extensions.
%%-----------------------------------------------------------------------------
\newcommand\ReplaceEveryHash[1]{%
  \romannumeral0\UD@ReplaceEveryHashLoop{#1}{}%
}%
\newcommand\UD@ReplaceEveryHashLoop[2]{%
  \UD@CheckWhetherNull{#1}{ #2}{%
    \UD@CheckWhetherLeadingSpace{#1}{%
       \expandafter\UD@ReplaceEveryHashLoop
       \expandafter{\UD@removespace#1}{#2 }%
    }{%
      \UD@CheckWhetherBrace{#1}{%
        \expandafter\expandafter\expandafter\UD@PassFirstToSecond
        \expandafter\expandafter\expandafter{%
        \expandafter\UD@PassFirstToSecond\expandafter{%
            \romannumeral0\expandafter\UD@ReplaceEveryHashLoop
            \romannumeral0\UD@ExtractFirstArgLoop{#1\UD@SelDOm}{}%
        }{#2}}%
        {\expandafter\UD@ReplaceEveryHashLoop
         \expandafter{\UD@firstoftwo{}#1}}%
      }{%
       \expandafter\UD@CheckWhetherHash
       \romannumeral0\UD@ExtractFirstArgLoop{#1\UD@SelDOm}{#1}{#2}%
      }%
    }%
  }%
}%
\newcommand\UD@CheckWhetherHash[3]{%
  \expandafter\UD@CheckWhetherLeadingSpace\expandafter{\string#1}{%
    \expandafter\expandafter\expandafter\UD@CheckWhetherNull
    \expandafter\expandafter\expandafter{%
    \expandafter\UD@removespace\string#1}{%
      \expandafter\expandafter\expandafter\UD@CheckWhetherNull
      \expandafter\expandafter\expandafter{%
      \expandafter\UD@removespace\detokenize{#1}}{% Something whose stringification yields a single space
        \expandafter\UD@ReplaceEveryHashLoop
        \expandafter{\UD@firstoftwo{}#2}{#3#1}%
      }{% Explicit space of catcode 6
        \expandafter\expandafter\expandafter\UD@PassFirstToSecond
        \expandafter\expandafter\expandafter{\expandafter\UD@Exchange
        \expandafter{\string#1}{#3}}{%
          \expandafter\UD@ReplaceEveryHashLoop
          \expandafter{\UD@firstoftwo{}#2}%
        }%
      }%
    }{% Something whose stringification has a leading space
      \expandafter\UD@ReplaceEveryHashLoop
      \expandafter{\UD@firstoftwo{}#2}{#3#1}%
    }%
  }{%
    \expandafter\expandafter\expandafter\UD@CheckWhetherNull
    \expandafter\expandafter\expandafter{%
    \expandafter\UD@firstoftwo
    \expandafter{\expandafter}\string#1}{%
      \expandafter\expandafter\expandafter\UD@CheckWhetherNull
      \expandafter\expandafter\expandafter{%
      \expandafter\UD@firstoftwo
      \expandafter{\expandafter}\detokenize{#1}}{% No Hash
        \expandafter\UD@ReplaceEveryHashLoop
        \expandafter{\UD@firstoftwo{}#2}{#3#1}%
      }{% Hash
        \expandafter\expandafter\expandafter\UD@PassFirstToSecond
        \expandafter\expandafter\expandafter{\expandafter\UD@Exchange
        \expandafter{\string#1}{#3}}{%
          \expandafter\UD@ReplaceEveryHashLoop
          \expandafter{\UD@firstoftwo{}#2}%
        }%
      }%
    }{% No Hash
      \expandafter\UD@ReplaceEveryHashLoop
      \expandafter{\UD@firstoftwo{}#2}{#3#1}%
    }%
  }%
}%
%----------------------------------------------------------------------
\makeatother

\begin{document}

\expandafter\expandafter\expandafter\def
\expandafter\expandafter\expandafter\mytempa
\expandafter\expandafter\expandafter{\ReplaceEveryHash{F#m.png}}

\includegraphics[width=5cm]{\mytempa}

\end{document}

しかし、ハッシュを置き換えるだけでは最善の解決策ではありません。理由: ハッシュの他に、ファイル名には不均衡な中括弧などが含まれる可能性があります。したがって、.tex 入力ファイルから読み取り、マクロ引数を逐語的カテゴリ コード レジームでトークン化するルーチンが便利かもしれません。

\UDcollectverbarg次の構文のマクロを提供できます。

\UDcollectverbarg{⟨^^M-replacement⟩}{⟨mandatory 1⟩}{⟨mandatory 2⟩}⟨verbatimized argument⟩

その結果は次のようになります。

⟨mandatory 1⟩{⟨mandatory 2⟩{⟨verbatim argument⟩}}

行の終わりを示す各文字は^^Mトークンシーケンスに置き換えられます⟨^^M-replacement⟩

引数⟨mandatory 1⟩と は⟨mandatory 2⟩必須です。複数のトークンで構成される場合、これらのトークンは catcode-1/2-explicit-character-token-pair / の中括弧にネストする必要があります。
読み取りとトークン化が必要な場合は、変更されていないカテゴリ コード レジームで行われます。 も必須です。これは、逐語的なカテゴリ コード レジームで読み取りとトークン化を行う必要があります。
最初⟨verbatim argument⟩の文字が中括弧の場合、引数が中括弧にネストされていると「想定」されます。それ以外の場合は、引数の終わりが最初の文字で区切られていると想定されます ( の引数と同様) \verb
空行は無視されません。

この構文を選択したのは、内で⟨mandatory 2⟩の呼び出しをネストすることで、内で逐語的な引数を収集できるためです。\UDcollectverbarg⟨mandatory 1⟩

例えば、

\UDcollectverbarg{<^^M-replacement>}%
                 {\UDcollectverbarg{<^^M-replacement>}{\UDcollectverbarg{<^^M-replacement>}{<actionA>}}}% <- mandatory 1
                 {<actionB>}%                     <- mandatory 2
                 <verbatim argument 1><verbatim argument 2><verbatim argument 3>

結果:

\UDcollectverbarg{<^^M-replacement>}{\UDcollectverbarg{<^^M-replacement>}{<actionA>}}% <- mandatory 1
                 {<actionB>{<verbatimd argument 1>}}%        <- mandatory 2
                 <verbatim argument 2><verbatim argument 3>

結果:

\UDcollectverbarg{<^^M-replacement>}{<actionA>}% <- mandatory 1
                 {<actionB>{<verbatim argument 1>}{<verbatim argument 2>}}% <- mandatory 2
                 <verbatim argument 3>

結果:

<actionA>{<actionB>{<verbatim argument 1>}{<verbatim argument 2>}{<verbatim argument 3>}}

仮定<actionA>= \@firstofone:

\@firstofone{<actionB>{<verbatim argument 1>}{<verbatim argument 2>}{<verbatim argument 3>}}

結果:

<actionB>{<verbatim argument 1>}{<verbatim argument 2>}{<verbatim argument 3>}

% This example does not require eTeX extensions.

\errorcontextlines=10000

\makeatletter
%%<-------------------- Code for \UDcollectverbarg -------------------->
%% Copyright (C) 2007 - 2019 by Ulrich Diez ([email protected])
%%
%% This work may be distributed and/or modified under the
%% conditions of the LaTeX Project Public Licence (LPPL), either
%% version 1.3 of this license or (at your option) any later
%% version. (The latest version of this license is in:
%% http://www.latex-project.org/lppl.txt
%% and version 1.3 or later is part of all distributions of LaTeX
%% version 1999/12/01 or later.)
%% The author of this work is Ulrich Diez.
%% This work has the LPPL maintenance status 'not maintained'.
%% Usage of any/every component of this work is at your own risk.
%% There is no warranty - neither for probably included
%% documentation nor for any other part/component of this work.
%% If something breaks, you usually may keep the pieces.
%
\newcommand\UD@firstofone[1]{#1}%
\newcommand\UD@firstoftwo[2]{#1}%
\newcommand\UD@secondoftwo[2]{#2}%
%%
%% Check whether argument is empty:
%%......................................................................
%% \UD@CheckWhetherNull{<Argument which is to be checked>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is empty>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is not empty>}%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
\newcommand\UD@CheckWhetherNull[1]{%
  \romannumeral0\expandafter\UD@secondoftwo\string{\expandafter
  \UD@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
  \UD@secondoftwo\string}\expandafter\UD@firstoftwo\expandafter{\expandafter
  \UD@secondoftwo\string}\expandafter\expandafter\UD@firstoftwo{ }{}%
  \UD@secondoftwo}{\expandafter\expandafter\UD@firstoftwo{ }{}\UD@firstoftwo}%
}%
%%......................................................................
\begingroup
\catcode`\^^M=12 %
\UD@firstofone{%
  \endgroup%
  \newcommand\UDEndlreplace[2]{\romannumeral0\@UDEndlreplace{#2}#1^^M\relax{}}%
  \newcommand*\@UDEndlreplace{}%
  \long\def\@UDEndlreplace#1#2^^M#3\relax#4#5{%
    \UD@CheckWhetherNull{#3}%
    { #5{#4#2}}{\@UDEndlreplace{#1}#3\relax{#4#2#1}{#5}}%
  }%
}%
\newcommand\UDcollectverbarg[3]{%
  \begingroup
  \let\do\@makeother % <- this and the next line switch to
  \dospecials        %    verbatim-category-code-régime.
  \catcode`\{=1      % <- give opening curly brace the usual catcode so a 
                     %    curly-brace-balanced argument can be gathered in
                     %    case of the first thing of the verbatimized-argument 
                     %    being a curly opening brace.
  \catcode`\ =10     % <- give space and horizontal tab the usual catcode so \UD@collectverbarg
  \catcode`\^^I=10   %    cannot catch a space or a horizontal tab as its 4th undelimited argument.
                     %    (Its 4th undelimited argument denotes the verbatim-
                     %     syntax-delimiter in case of not gathering a
                     %     curly-brace-nested argument.)
  \kernel@ifnextchar\bgroup
  {% seems a curly-brace-nested argument is to be caught:
    \catcode`\}=2    % <- give closing curly brace the usual catcode also.
    \UD@collectverbarg{#1}{#2}{#3}{}%
  }{% seems an argument with verbatim-syntax-delimiter is to be caught:
    \do\{% <- give opening curly brace the verbatim-catcode again.
    \UD@collectverbarg{#1}{#2}{#3}%
  }%
}%
\newcommand\UD@collectverbarg[4]{%
  \do\ %   <- Now that \UD@collectverbarg has the delimiter or
  \do\^^I%    emptiness in its 4th arg, give space and horizontal tab
         %    the verbatim-catcode again.
  \do\^^M% <- Give the carriage-return-character the verbatim-catcode.
  \long\def\@tempb##1#4{%
    %\edef\@tempb{##1}%
    \def\@tempb{##1}%
    \@onelevel@sanitize\@tempb % <- Turn characters into their "12/other"-pendants.
                               %    This may be important with things like the 
                               %    inputenc-package which may make characters 
                               %    active/which give them catcode 13(active).
    \expandafter\UDEndlreplace\expandafter{\@tempb}{#1}{\def\@tempb}% <- this starts 
                               %    the loop for replacing endline-characters.
    \expandafter\UD@@collectverbarg\expandafter{\@tempb}{#2}{#3}% <- this "spits 
                               %    out the result.
  }%
  \@tempb
}%
\newcommand\UD@@collectverbarg[3]{%
  \endgroup
  #2{#3{#1}}%
}%
%%<---------------- End of code for \UDcollectverbarg ----------------->
\makeatother

\documentclass{article}
\usepackage{graphicx}

\begin{document}

\begingroup\catcode`\^^M=12\relax%
\UDcollectverbarg{^^M}{\endgroup\csname @firstofone\endcsname}{\def\mytempa}|F#m.png|%

\includegraphics[width=5cm]{\mytempa}

\end{document}

関連情報