Geht das irgendwie? Elementar (also ohne xparse, etoolbox usw.) wäre gut, sofern möglich.

Ich möchte im Besonderen wissen, ob ein Minuszeichen vorkommt.

Hinweis: Prüfen auf ein Zeichen reicht.

Peudo-MWE:

Öffne in Overleaf
\documentclass[margin=5mm, varwidth]{standalone}
\begin{document}
Pseudocode:

\ ifexists{a <oder> $-$ <Minuszeichen>} in {Hier ein Text ohne a, aber mir Minuszeichen:$-3$} ja
\ else nein
\ fi

\end{document}

gefragt 12 Okt '18, 10:55

cis's gravatar image

cis
9.3k20201323
Akzeptiert: 62%

bearbeitet 12 Okt '18, 10:56

Elementar ist es mit expl3. Warum willst du dir das Leben schwer machen, indem du auf solche Tools verzichtest?

(12 Okt '18, 11:44) Ulrike Fischer

Ich habe ein paar Lösungen hier gefunden:

https://tex.stackexchange.com/questions/26870/check-if-a-string-contains-a-given-character

Sie beantworten vermutlich die Frage im allgemeinen - kann man im Grunde hier schließen. Helfen mir leider bei meinem speziellen Problem nicht weiter.

(12 Okt '18, 13:59) cis

Testen, ob das Zeichen im Mathemodus oder nicht verwendet wird, könnte allerdings ein wenig haariger werden...

(12 Okt '18, 18:29) Skillmon

Hintergrund: In polynom.sty gibt es den \polyremainder, der Rest ist z.B. 3 oder -8. Für [Wie lasse ich mir nur das Ergebnis einer Polynomdivision anzeigen?] dachte ich, man könnte den \polyremainder darauf testen, ober er positiv oder negativ ist. polynom.sty ist sehr professionell geschrieben, für mich schwierig zu verstehen. Es wäre so schön einfach gewesen,wenn sie einen Schalter \polyset{calc=false} eingebaut hätten-haben sie aber nicht

(13 Okt '18, 10:29) cis

Jetzt muss man sich den Kram kompliziert zusammenbasteln. So oder so müsste eine Zeichentestmethode vermutlich sehr professionell sein, wenn die rausfinden soll, das \polyprint{\polyremainder} ein Minus dran hat, wenn der \polyremainder -8 ist. Insofern glaube ich, dass dieser Ansatz eh keine gute Idee ist. Die Lösung steht eher in der Paketdatei polynom.sty aber die ist für mich eben kompliziert zu verstehen.

(13 Okt '18, 10:34) cis

Wenn es sich bei dem Ergebnis garantiert um eine Ganzzahl handelt, kannst du auch ganz einfach mit \ifnum#1<0 testen. Bei einer Gleitpunktzahl kannst du mit \ifdim#1pt<0pt das Gleiche machen.

(13 Okt '18, 12:33) Skillmon

An sich nein (der Rest kann auch rational sein), ich glaube aber, dass polyprint{polyremainder}(=> z.B.-8) eh keine "Zahl" ist; vll. ein String, ich kenne mich zu wenig aus... Andererseits glaube ich, dass diese Art des Testens, beim genannten Problem im Link, eh Schmarn ist. An sich enthältpolynom.sty` alles Nötige, möchte aber das Ergebnis einer Polynomdivision nur in Verbindung mit der Rechnung ausgeben. Ich schaffe es nicht, das reine Ergebnis aus der Paketdatei herauszufiltern... :(

(13 Okt '18, 13:29) cis

PS: @Skillmon Du hast nicht zufällig Lust, mal in polynom.sty zu schauen? Das liest doch Du wie ein Roman... ;)

(13 Okt '18, 13:42) cis

@cis das sind über 1700 Zeilen Code. Ich glaube, du überschätzt meine Fähigkeiten.

(13 Okt '18, 14:42) Skillmon

Ach die relevanten Stellen, die Kommandos oder so, finde sogar ich schnell. Auch habe ich bei tex.stackexchange kleinere Manipulationen gesehen. Bloß mein Problem bekomme ich nicht gelöst. :(

(13 Okt '18, 14:46) cis
Ergebnis 5 von 10 Alle anzeigen

Also, wenn es nicht expandierbar sein muss, kannst du dir ein temporäres Macro definieren und damit testen:

Zunächst brauchen wir eine Art, wie wir testen können, ob ein bestimmter Token in einer Zeichenfolge vorkommt, das Folgende implementiert einen solchen Test für den Token a:

Öffne in Overleaf
\def\tokentest@a #1a#2\endtokentest@a%
  {%
    \if\relax\detokenize{#2}\relax
      <no a contained>
    \else
      <a contained>
    \fi
  }
% usage:
\tokentest@a <string>a\endtokentest@a

Der Test funktioniert folgendermaßen: Das Macro \tokentest@a liest in seinem ersten Argument alles, bis zu einem a, das zweite Argument ist alles bis zum \endtokentest@a (statt dieses (nicht definierten) Kontrollwortes kannst du auch jede beliebige andere, extrem unwahrscheinliche Zeichenfolge verwenden). Durch den Aufruf, in dem immer ein a direkt vor \endtokentest@a definiert wird, ist das zweite Argument leer, wenn das erste kein a enthält. Der Test \if\relax\detokenize{#2}\relax ist ein expandierbarer und sicherer Test auf ein leeres Argument.

Nun brauchen wir das Ganze aber ein wenig dynamischer, da das erste Argument ja angeben soll, auf welche Zeichen geprüft wird. Also definieren wir uns ein Macro, das ein Testmacro wie oben definiert. Wir geben auch direkt vor, was in welchem Fall jeweils passieren soll:

Öffne in Overleaf
\newcommand\ifexists@define[1]
  {%
    \long\def\ifexists@test ##1#1##2\endifexists@test
      {%
        \if\relax\detokenize{##2}\relax
        \else
          \let\ifexists@if\iftrue
        \fi
      }%
  }

Das Macro nimmt als Argument diejenige Zeichenfolge, auf die geprüft werden soll. Wir benötigen nur eine Aktion für den Fall, dass das Zeichen vorkommt, in welchem wir ein Hilfsmacro \ifexists@if zu \iftrue werden lassen (der andere Fall ist somit implizit abgedeckt, eben wenn \ifexists@if nicht \iftrue entspricht).

Zusätzlich definieren wir uns noch ein Macro, das uns den Test ein wenig vereinfacht (wir benötigen es später, weil wir Argument 1 expandieren müssen):

Öffne in Overleaf
\newcommand\ifexists@test@helper[2]
  {%
    \ifexists@test#2#1\endifexists@test
  }

Schließlich noch das eigentliche Macro, welches über die angegebenen gesuchten Zeichen iteriert und für jedes den Test durchführt. Hierfür verwende ich \@for aus dem LaTeX-Kernel.

Öffne in Overleaf
\long\def\ifexists #1 in #2%
  {%
    \begingroup
    \let\ifexists@if\iffalse
    \@for\zz:={#1}\do
      {%
        \expandafter\ifexists@define\expandafter{\zz}%
        \expandafter\ifexists@test@helper\expandafter{\zz}{#2}%
      }%
    \expandafter\endgroup\ifexists@if
    \ignorespaces
  }

Das Macro ignoriert Leerzeichen nach seinem zweiten Argument. Du kannst mit dem Macro nicht auf ein Komma im String prüfen, da sich das nicht mit der Syntax von \@for vertragen würde.

Komplettes MWE:

Öffne in Overleaf
\documentclass[border=2mm]{standalone}

\makeatletter
\newcommand\ifexists{}% test whether there are conflicts
\long\def\ifexists #1 in #2%
  {%
    \begingroup
    \let\ifexists@if\iffalse
    \@for\zz:={#1}\do
      {%
        \expandafter\ifexists@define\expandafter{\zz}%
        \expandafter\ifexists@test@helper\expandafter{\zz}{#2}%
      }%
    \expandafter\endgroup\ifexists@if
    \ignorespaces
  }
\newcommand\ifexists@define[1]
  {%
    \long\def\ifexists@test ##1#1##2\endifexists@test
      {%
        \if\relax\detokenize{##2}\relax
        \else
          \let\ifexists@if\iftrue
        \fi
      }%
  }
\newcommand\ifexists@test@helper[2]
  {%
    \ifexists@test#2#1\endifexists@test
  }
\makeatother

\begin{document}
\ifexists{a,e,f} in {abc}
  yep
\else
  nope
\fi
\end{document}

Soll immer auf die gleichen Token geprüft werden, ist obiges ohne Probleme auch expandierbar umsetzbar.

Zum Vergleich der Aufwand bei Verwendung von xparse und expl3 (keine Schleife, sondern nur ein Test, ob #1 in #2 vorkommt):

Öffne in Overleaf
\documentclass[border=2mm]{standalone}

\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand \ifexists { +m +m }
  {
    \tl_if_in:nnTF { #2 } { #1 }
  }
\ExplSyntaxOff

\begin{document}
\ifexists{a}{abc}
  {yep}
  {nope}
\end{document}
Permanenter link

beantwortet 12 Okt '18, 18:09

Skillmon's gravatar image

Skillmon
6664

bearbeitet 13 Okt '18, 12:32

In beiden Fällen (Verwendung von expl3 und mein Stümpermacro) lässt sich die gesuchte Zeichenfolge durch geschweifte Klammern verstecken. Der Test \ifexists{a} in {{a}bc} würde also das a nicht finden.

(12 Okt '18, 18:17) Skillmon

Oha. Wenn ich \ifexists{e,f} in {abc} mache im Vorletzten Code, kommt eine Fehlermeldung.

(13 Okt '18, 08:18) cis

@cis oh, ich hatte an einer Stelle die falsche Reihenfolge bei \expandafter... Man sollte Code vernünftig testen :)

(13 Okt '18, 12:31) Skillmon
Deine Antwort auf die Frage (nicht auf andere Antworten)
Knebel-Vorschau

Folge dieser Frage

Per E-Mail:

Wenn Du Dich anmeldest, kannst Du Updates hier abonnieren

Per RSS:

Antworten

Antworten und Kommentare

Markdown-Grundlagen

  • *kursiv* oder _kursiv_
  • **Fett** oder __Fett__
  • Link:[Text](http://url.com/ "Titel")
  • Bild?![alt Text](/path/img.jpg "Titel")
  • nummerierte Liste: 1. Foo 2. Bar
  • zum Hinzufügen ein Zeilenumbruchs füge einfach zwei Leerzeichen an die Stelle ein, an der die neue Zeile sein soll.
  • grundlegende HTML-Tags werden ebenfalls unterstützt

Zugeordnete Themen:

×48

Frage gestellt: 12 Okt '18, 10:55

Frage wurde angeschaut: 709 Mal

Zuletzt aktualisiert: 13 Okt '18, 14:46