7

During pdfLaTeX processing, I'm writing a string of key-value pairs to an external file. Sometimes the value will contain \# and I want only the # to be written to the file.

Here is my code which works fine as long as I just need to write plain text. Assume that every key is defined as \@empty by default; it is only written to the file if it has a value other than \@empty.

e.g. \def\objects{\@empty}\def\mystring{\@empty}

\newcommand{\setoptions}{%
  \global\edef\finaloption{}
  \getkeyval{objects}\getkeyval{mystring}
}
\newcommand{\getkeyval}[1]{%
  \def\tmpkey{#1}
  \edef\tmpval{\csname #1\endcsname}
  \ifx\@empty\tmpval
  \else
  \edef\finaloption{\finaloption,\tmpkey=\tmpval}
  \fi
}

Then later this line writes the key-value pairs to the external file:

\setoptions
\immediate\write\mypgm{\finaloption}

I suppose I need to loop through \tmpval checking for \char23? Is that a step in the right direction?

Edit: An example of the LaTeX input:

\mytag[mystring=val, objects=App\#1 App\#2,caption={my title}]{myarg}

I parse and retrieve the key-value pairs and I want to write this line to the external file:

mystring=val, objects=App#1 App#2
  • 1
    It would be better if you limit your question to the core issue (the writing of the hash char). Having all the keyval things on top just makes it harder to see what you want. – Martin Scharrer Dec 9 '11 at 20:34
  • \char23 and # are not always the same. While both will typeset the same character, the first doesn't expand to the latter. Also do you really have \# or #? In the case of \#, just redefine that macro (!) to produce a verbatim #. – Martin Scharrer Dec 9 '11 at 20:36
  • thanks. That answer is for a different situation where the special characters are desired in the external file. I have source with the character escaped (so LaTeX has no problem) and I want to write it out unescaped. Sorry I wasn't clear on that. – Tim A Dec 9 '11 at 21:08
9

You can simply locally redefine \#, which is a macro (a control character to be specific, normal macros are control words) to expand to a verbatim #. This can be simply done using the newverbs package which provides \Verbdef.

% Preamble
\usepackage{newverbs}

% write code
\begingroup
\Verbdef\#{#}%
\immediate\write\mypgm{\finaloption}%
\endgroup

Without this package you can do it the following way:

% outside of any macro
% globally defines a macro \hashchar which holds a verbatim `#`
\begingroup
\catcode`\#=12
\gdef\hashchar{#}%
\endgroup

% write code
\begingroup
\let\#\hashchar
\immediate\write\mypgm{\finaloption}%
\endgroup

Usually people would use \@hashchar (requires \makeatletter .. \makeatother outside package or class files) to reduce the risk of name clashes.

(Not tested due to the lack of a MWE.)

  • Thanks. I didn't see how to create a MWE but I will try harder next time. I was trying to show the method I was using. I did exactly what you said with the macros and it works great. – Tim A Dec 9 '11 at 21:28
1

I would defer the execution of the macro when # has category code 12:

\newcommand{\getkeyval}{\begingroup\catcode`#=12 \@getkeyval}
\newcommand{\@getkeyval}[1]{%
  \edef\tmpval{\csname #1\endcsname}%
  \ifx\@empty\tmpval
  \else
    \xdef\finaloption{\finaloption,#1=\tmpval}%
  \fi
  \endgroup}

You should not write \# in the argument, but only #. Seeing a "real life" example would be useful.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.