12

I have a value defined in a macro, e.g.:

\mymacro{apple}

I need to check if a value does not equal a string, e.g.:

IF #1 NOT EQUAL TO "apple" THEN
    PRINT "It is not a apple, it is #1."
FI

I have tried using this, but it does not work:

\ifx#1="apple"
\else
    It is not a apple, it is #1.
\fi

I have also tried using this, but it also does not work:

\startlua
    if #1 ~= "apple" then
        context("It is not a apple, it is #1.")
    end
\stoplua
  • The macro might be set to any value.
  • If anything other than "apple" appears inside, including TeX commands which do not create output, it should still be considered a negative result.

How can I create a plain TeX or Lua conditional which checks if the value is not equal?

Village
  • 13,603
  • 23
  • 116
  • 219

3 Answers3

14

You can define a command that expands to "apple", another that expands to whatever you want to test, and then use \ifx. Here's a latex file that demonstrates this:

\documentclass{article}

\begin{document}

\def\appleref{apple}
\def\testit#1{%
  \def\temp{#1}%
  \ifx\temp\appleref
    Yes, it's apple.
  \else
    No, it's #1.
  \fi
}


apple: \testit{apple}

pear: \testit{pear}

\def\fakeapple{apple}

fakeapple: \testit{\fakeapple}

\end{document}

Edit: tohecz points out in a comment that if you change \def\temp{#1} to \edef\temp{#1}, then \fakeapple (which is a macro that expands to "apple") would test as being equal to "apple".

  • If you wanted \fakeapple to pass the test as an apple, you could change \def to \edef in \def\temp{#1}% . – yo' May 06 '12 at 05:31
  • @tohecz: Yes, but I didn't want it to pass. I used it to show that a macro expanding to "apple" is not treated the same as the actual string "apple". – Phil Hirschhorn May 06 '12 at 05:52
  • I know. I've pointed it out just in case that somebody were looking for this variant of the solution ;) – yo' May 06 '12 at 05:54
  • @tohecz: Ah, I misunderstood. Yes, it's a good thing to point out. – Phil Hirschhorn May 06 '12 at 05:56
  • I should have said "If somebody wanted ..." and it would be clear ;) Feel free to remark it in the answer itself ;) – yo' May 06 '12 at 06:15
  • One could modify the code to be plain tex by removing the \documentclass{article}, \begin{document}, and changing the \end{document} into \bye. – morbusg May 06 '12 at 06:33
  • 2
    Note that \ifx comparison is catcode sensitive, so it doesn't work if one of the strings uses 12 (other) instead of 11 (letter), which is the case of strings provided by TeX like \jobname. In this case you can use \@onelevel@sanitize\@tempa and the same for \appleref to make every letter catcode 12. – Martin Scharrer May 06 '12 at 07:31
  • you really don't need LaTeX: this code should also work on Plain, right? – jarnosc Sep 23 '16 at 16:09
  • @erreka: That's right, this is all plain TeX, although it also works in LaTeX. – Phil Hirschhorn Sep 24 '16 at 13:48
11

ConTeXt provides a \doif... series of macros to do string comparisons. See the ConTeXt wiki for details. For example, if you want check if #1 is the same as a previously defined macro \fakeapple, then you can use:

\def\checkapple#1%
    {\doifnot\fakeapple{#1}
       {It is not an apple, it is #1}}
Aditya
  • 62,301
  • What is \fakeapple here? (I guess \checkapplie is a typo for \checkapplebut couldn't figure out \fakeapple: is it a macro defined as the string "apple"?) – ShreevatsaR Sep 21 '16 at 19:14
  • 1
    @ShreevatsaR: Yes, \checkaplie was a typo. I used \fakeapple because it was used in a previous reply by Phil Hirschhorn. I added some more details in my solution. – Aditya Sep 22 '16 at 01:09
2

Under pdfTeX you can perform string comparisons using \pdfstrcmp{<strA>}{<strB>}. From the pdfTeX user manual:

\pdfstrcmp{<general text>}{<general text>} (expandable)

This command compares two strings and expands to 0 if the strings are equal, to -1 if the first string ranks before the second, and to 1 otherwise. The primitive was introduced in pdfTEX 1.30.0.

enter image description here

\documentclass{article}

\begin{document}

\def\appleref{apple}
\def\testit#1{%
  \ifnum\pdfstrcmp{#1}{apple}=0
    Yes, it's apple.
  \else
    No, it's #1.
  \fi
}

apple: \testit{apple}

pear: \testit{pear}

\def\fakeapple{apple}

fakeapple: \testit{\fakeapple}

\end{document}
Werner
  • 603,163