5

I want to read a line of file and compare it to a predefined macro with the aid of \ifx. The following MWE shows my problem, I was expected to get Equal, but I get Not Equal.

\documentclass{article}

\usepackage{filecontents}
\begin{filecontents*}{\jobname.txt}
latex
\end{filecontents*}

\def\test{latex}

\begin{document}
    \newread\reader%
    \openin\reader=\jobname.txt\relax%
    \readline\reader to \data%
    \closein\reader%
    \ifx\data\test Equal\else Not Equal\fi
\end{document}
1
  • 2
    Because the EOL token is also part of \data. Use \show\data after you read in the line to see this.
    – Skillmon
    Dec 5, 2017 at 13:51

3 Answers 3

7

NO ADDITIONAL PACKAGES

Change the \catcode of \endlinechar (from 5-end-of-line to 9-ignore) and do a \read instead of \readline.

\documentclass{article}
\usepackage{filecontents}
\begin{filecontents*}{\jobname.txt}
latex
\end{filecontents*}
\def\test{latex}

\begin{document}
{
    \catcode\endlinechar=9 %
    \newread\reader%
    \openin\reader=\jobname.txt\relax%
    \read\reader to \data%
    \closein\reader%
    \ifx\data\test Equal\else Not Equal\fi
}
\end{document}

enter image description here

There are several similar alternatives to this: changing the catcode of \endlinechar can be omitted if the end-of-line is removed from the created file via the trailing %:

\begin{filecontents*}{\jobname.txt}
latex%
\end{filecontents*}

Alternately, the catcode change can also be omitted, even if the file does not end in a %, but if the test string has a space added to the end

\def\test{latex }

This is because the end-of-line, upon digestion, is transliterated to a space character.

readarray ANSWER

readarray package can read the file as a \def. Then, I only need to truncate the trailing space to prepare for the comparison.

\documentclass{article}
\usepackage{readarray}
\usepackage{filecontents}
\begin{filecontents*}{\jobname.txt}
latex
\end{filecontents*}
\newcommand\removetrailingspaces[1]{\expandafter\rtsaux#1\endrts}
\def\rtsaux#1 \endrts{#1}
\def\test{latex}

\begin{document}
    \readdef{\jobname.txt}\dataraw
    \edef\data{\removetrailingspaces{\dataraw}}
    \ifx\data\test Equal\else Not Equal\fi
\end{document}

Alternately, the comparison string can be defined with a trailing space, to avoid the truncation altogether:

\documentclass{article}
\usepackage{readarray}
\usepackage{filecontents}
\begin{filecontents*}{\jobname.txt}
latex
\end{filecontents*}
\def\test{latex }

\begin{document}
    \readdef{\jobname.txt}\dataraw
    \ifx\dataraw\test Equal\else Not Equal\fi
\end{document}
5

Here is a workaround using LaTeX3:

\documentclass{article}

\usepackage{expl3}

\usepackage{filecontents}
\begin{filecontents*}{\jobname.txt}
latex
\end{filecontents*}

\ExplSyntaxOn
\ior_new:N \l_data_file
\ior_open:Nn \l_data_file {\jobname.txt}
\ior_get:NN \l_data_file \data
\ior_close:N \l_data_file
\ExplSyntaxOff

\def\test{latex}

\begin{document}
    \ifx\data\test Equal\else Not Equal\fi
\end{document}

Just for the record, the output is:

enter image description here

1
  • I was asking myself how to get that EOL-token into the test string. Chopping it off during the read process seems wrong to me :)
    – Skillmon
    Dec 5, 2017 at 14:20
2

There are two issues:

  1. the \endlinechar should be removed
  2. \readline makes a string (catcode 12 characters, catcode 10 spaces)

Thus the \test macro should be “stringified”; in order to remove the end-of-line, some group trickery is also needed.

\begin{filecontents*}{\jobname.txt}
latex
\end{filecontents*}

\documentclass{article}

\edef\test{\detokenize{latex}}
\newread\reader%


\begin{document}

\openin\reader=\jobname.txt\relax
\begingroup
\endlinechar=-1
\readline\reader to \temp
\edef\x{\endgroup\def\noexpand\data{\temp}}\x
\closein\reader
\ifx\data\test Equal\else Not Equal\fi

\end{document}

A shorter solution, where it is assumed the auxiliary file is a one-liner.

\begin{filecontents*}{\jobname.txt}
latex
\end{filecontents*}

\documentclass{article}
\usepackage{catchfile}

\def\test{latex}

\begin{document}

\CatchFileDef\data{\jobname.txt}{\endlinechar=-1 }
\ifx\data\test Equal\else Not Equal\fi

\end{document}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .