持っていない人のために\regex_replace_all:nnN

持っていない人のために\regex_replace_all:nnN

読み取ってプロットしたい表がいくつかありますが、それぞれに独自のスタイルがあります。便宜上、同じタグを使用するのが好きです。以下は MWE です。

\documentclass{minimal}

\usepackage{pgfplotstable}

\begin{filecontents}{tabA.dat}
x   y
0   0
1   1
2   2
3   3
\end{filecontents}
\begin{filecontents}{tabB.dat}
x   y
0   1
1   2
2   3
3   4
\end{filecontents}

\pgfplotsset{compat=newest,
tabA/.style={color=red,mark=*},
tabB/.style={color=black,mark=o},
}

\pgfplotstableread{tabA.dat}\tabA
\pgfplotstableread{tabB.dat}\tabB

\begin{document}
    \begin{tikzpicture}
        \begin{axis}[legend,legend pos=south east]
            \addplot[tabA] table[x=x,y=y] {\tabA};\label{pgf:tabA}\addlegendentry{tabA}
            \addplot[tabB] table[x=x,y=y] {\tabB};\label{pgf:tabB}\addlegendentry{tabB}
        \end{axis}
    \end{tikzpicture}

\end{document}

\pgfplotsforeachinvokeまたは を使って同じ結果を得ることができますか\foreach

\begin{tikzpicture}
    \begin{axis}[legend,legend pos=south east]
        \pgfplotsinvokeforeach{tabA,tabB}{%
            % The following doesn't work, of course
            \addplot[#1] table[x=x,y=y] {\#1}; % <- Magic goes here 
        }
    \end{axis}
\end{tikzpicture}

もちろん、この単純なケースでは、

\addplot[#1] table[x=x,y=y] {#1.dat};

しかし、ファイル名がパターンに従っていない場合や、テーブルを読み取って保存し、それを変更したり、何度も再利用したりしたい場合もあります。

答え1

TeX.SE へようこそ! 常に可能なことが 1 つあります。

  1. トークン リストを希望どおりに組み立てるマクロを記述する (ここでは、\addplot適切なオプションを使用して一連のコマンドを連結します)。

  2. \foreachTable次に、のような出力を出力する2 番目のマクロ (私のコードでは、 の 2 番目の引数から構築されています) を使用します。ここで、 は\begin{axis}[...]#1\end{axis}#1すべてのコマンドを含む以前に組み立てられたトークン リストに置き換えられます\addplot

この技術常に機能する(2 番目のマクロが展開されると、TeX 入力ストリームは、すべてのコードを手動で入力した場合とまったく同じ状態になります)。したがって、これを使用して、表、画像など、必要なものをプログラムで生成できます。

完全なコード:

\begin{filecontents}{tabA.dat}
x   y
0   0
1   1
2   2
3   3
\end{filecontents}

\begin{filecontents}{tabB.dat}
x   y
0   1
1   2
2   3
3   4
\end{filecontents}

\documentclass[tikz, border=2mm]{standalone}
\usepackage{xparse}
\usepackage{pgfplots}
\pgfplotsset{compat=1.16}

\ExplSyntaxOn
\seq_new:N \l__millo_plot_cmds_tl

\cs_new_protected:Npn \millo_foreach_table_do_axis:nNn #1#2#3
  {
    \tl_clear:N \l__millo_plot_cmds_tl
    \clist_map_inline:nn {#1}
      {
        \tl_set:Nn \l_tmpa_tl {#3}
        \regex_replace_all:nnN { \c{myTable} } { \c{##1} } \l_tmpa_tl
        \tl_put_right:NV \l__millo_plot_cmds_tl \l_tmpa_tl
      }

    \exp_args:No #2 \l__millo_plot_cmds_tl
  }

\NewDocumentCommand \foreachTable { m m m }
  {
    \cs_set_protected:Npn \__millo_axis_func:n ##1 {#2}
    \millo_foreach_table_do_axis:nNn {#1} \__millo_axis_func:n {#3}
  }
\ExplSyntaxOff

\pgfplotsset{
  tabA/.style={color=red,mark=*},
  tabB/.style={color=black,mark=o},
}

\pgfplotstableread{tabA.dat}\tabA
\pgfplotstableread{tabB.dat}\tabB

\begin{document}

\begin{tikzpicture}
  \foreachTable{tabA, tabB}
    {
      \begin{axis}[legend, legend pos=south east]
        #1
      \end{axis}
    }
    { \addplot[#1] table[x=x,y=y] {\myTable}; \addlegendentry{#1} }
\end{tikzpicture}

\end{document}

スクリーンショット

通話の説明:

\foreachTable{tabA, tabB}
  {
    \begin{axis}[legend, legend pos=south east]
      #1
    \end{axis}
  }
  { \addplot[#1] table[x=x,y=y] {\myTable}; \addlegendentry{#1} }

最初の引数はエントリのリストです (各エントリは 1 つの\addplotコマンドにつながります)。

#12 番目の引数は、内部が自動的に生成されたコマンドによって置き換えられた後に挿入されるものです\addplot

3 番目の引数は、便利な置換を使用して、自動的に生成される各プロットのコードを指定します。

  • #1エントリ名に置き換えられます(ここではtabAthen tabB)。

  • \myTableエントリ名から構築された制御シーケンス トークンに置き換えられます (ここでは、\tabA最初のエントリの場合は 、\tabB2 番目のエントリの場合は )。

手動でさらにプロットを追加したい場合(ここでは、自動生成されたプロットの前後に 1 つずつ)、たとえば次のようにします。

\foreachTable{tabA, tabB}
  {
    \begin{axis}[legend, legend pos=south east]
      \addplot {sin(deg(\x))}; \addlegendentry{$\sin$}
      #1
      \addplot {sqrt(\x)};     \addlegendentry{$x\mapsto \sqrt{x}$}
    \end{axis}
  }
  { \addplot[#1] table[x=x,y=y] {\myTable}; \addlegendentry{#1} }

ここに画像の説明を入力してください

持っていない人のために\regex_replace_all:nnN

l3kernel古すぎて を取得できない場合は\regex_replace_all:nnN、次のことができます。

  • \cs_generate_variant:Nn \tl_replace_all:Nnn { Nno }の前に追加します\cs_new_protected:Npn \millo_foreach_table_do_axis:nNn #1#2#3

  • 行を置き換える

    \regex_replace_all:nnN { \c{myTable} } { \c{##1} } \l_tmpa_tl
    

    \exp_args:NNno
    \tl_replace_all:Nno \l_tmpa_tl { \myTable } { \use:c {##1} }
    

そうすればうまくいくはずだ条件で括弧内では使用しないでください\myTable。たとえば、

\foreachTable{tabA, tabB}
  {
    ...
  }
  { \addplot[#1] table[x=x,y=y] \myTable; \addlegendentry{#1} }

の代わりに:

\foreachTable{tabA, tabB}
  {
    ...
  }
  { \addplot[#1] table[x=x,y=y] {\myTable}; \addlegendentry{#1} }

関連情報