
Der folgende Code erzeugt das gewünschte Ergebnis, nämlich eine Liste der Zeilen mit XXX={<value>}
einem Wert <value>
, der nicht in der Liste der zulässigen Werte enthalten ist:
Diese Lösung erfordert jedoch, dass ich dieselben Informationen an zwei Stellen habe, was sehr fehleranfällig ist. Gibt es also eine Möglichkeit, die Makrosequenz grep -v
basierend auf dem Inhalt von zu generieren \ListOfAcceptableValues
?
Eine kompromisslose Lösung, die mir einfällt, ist die Verwendung mehrerer Dateien für jedes Element in der Liste der zulässigen Werte, aber ich denke, dass es dafür wahrscheinlich einen eleganteren Weg gibt.
Anmerkungen:
- Ich brauche es nur, damit es unter MacOS funktioniert, daher sind alle Unix-Dienstprogramme verfügbar.
- Ich verwende es
cat
hier, da es die tatsächliche Verwendung dieses Makros besser emuliert.
Code:
\documentclass{article}
\usepackage{datatool}
%\usepackage{filecontents}% Commented out to prevent overwriting FileA.tex
\begin{filecontents*}{FileA.tex}
XXX={AA}
some other tex content
XXX={YY}
XXX={BB}
and some more tex content
XXX={ZZ}
XXX={CC}
\end{filecontents*}
\begin{document}
\newcommand*{\ListOfAcceptableValues}{AA,BB,CC}%
%% How do I rewrite this to make use of \ListOfAcceptableValues
\immediate\write18{%
cat FileA.tex
| grep "XXX="
| grep -v AA
| grep -v BB
| grep -v CC
> FileB.tex
}
\DTLloadrawdb[noheader,keys={Problem}]{MyDB}{FileB.tex}%
\DTLdisplaydb{MyDB}
\end{document}
Antwort1
\def\foo#1,#2{| grep -v #1 \ifx\relax#2\else\expandafter\foo\expandafter#2\fi}
%% How do I rewrite this to make use of \ListOfAcceptableValues
\immediate\write18{%
cat FileA.tex
| grep "XXX="
\expandafter\foo\ListOfAcceptableValues,\relax
> FileB.tex
}
Antwort2
Eine reine LaTeX (3)-Lösung; die anfänglichen Leerzeichen bleiben allerdings nicht erhalten.
\begin{filecontents*}{FileA.tex}
XXX={AA}
some other tex content
XXX={YY}
XXX={BB}
and some more tex content
XXX={ZZ}
XXX={CC}
\end{filecontents*}
\documentclass{article}
\usepackage{datatool,xparse}
\ExplSyntaxOn
\seq_new:N \g_grill_acceptable_seq
\seq_new:N \l__grill_temp_seq
\ior_new:N \l_grill_input_stream
\iow_new:N \l_grill_output_stream
\NewDocumentCommand{\SetAcceptableValues}{m}
{
\seq_gset_split:Nnn \g_grill_acceptable_seq { , } { #1 }
}
\NewDocumentCommand{\ExamineFile}{mm}
{% #1 = input file, #2 = output file
\grill_examine_file:nn { #1 } { #2 }
}
\cs_new_protected:Npn \grill_examine_file:nn #1 #2
{
\ior_open:Nn \l_grill_input_stream { #1 }
\iow_open:Nn \l_grill_output_stream { #2 }
\ior_open:Nn \l_grill_input_stream { #1 }
\iow_open:Nn \l_grill_output_stream { #2 }
\ior_map_inline:Nn \l_grill_input_stream
{ \__grill_lookup_line:n { ##1 } }
\iow_close:N \l_grill_output_stream
\ior_close:N \l_grill_input_stream
}
\cs_new_protected:Npn \__grill_lookup_line:n #1
{
\seq_set_split:Nnn \l__grill_temp_seq { = } { #1 }
\int_compare:nT { \seq_count:N \l__grill_temp_seq = 2 }
{
\tl_if_eq:nxT { XXX } { \seq_item:Nn \l__grill_temp_seq { 1 } }
{
\seq_if_in:NxF \g_grill_acceptable_seq
{ \seq_item:Nn \l__grill_temp_seq { 2 } }
{
\iow_now:Nx \l_grill_output_stream { #1 }
}
}
}
}
\cs_generate_variant:Nn \tl_if_eq:nnT {nx}
\ExplSyntaxOff
\begin{document}
\SetAcceptableValues{AA,BB,CC}
\ExamineFile{FileA}{FileB}
\DTLloadrawdb[noheader,keys={Problem}]{MyDB}{FileB.tex}%
\DTLdisplaydb{MyDB}
\end{document}
Eine andere Lösung, die reguläre Ausdrücke verwendet; ich habe es \XXX
als Präfix hinzugefügt, wie Sie im Kommentar gefordert haben.
\begin{filecontents*}{FileA.tex}
\XXX={AA}
some other tex content
\XXX={YY}
\XXX={BB}
and some more tex content
\XXX={ZZ}
\XXX={CC}
\end{filecontents*}
\documentclass{article}
\usepackage{datatool,xparse,l3regex}
\newcommand{\XXX}{XXX} % just to print the database
\ExplSyntaxOn
\regex_new:N \g_grill_prefix_regex
%% Here you set the prefix
%% We specify \XXX, any number of spaces and =
\regex_gset:Nn \g_grill_prefix_regex { \c{XXX} \s*? = }
%%
\regex_new:N \l__grill_acceptable_regex
\seq_new:N \g_grill_acceptable_seq
\seq_new:N \l__grill_temp_seq
\ior_new:N \l_grill_input_stream
\iow_new:N \l_grill_output_stream
\NewDocumentCommand{\SetAcceptableValues}{m}
{
\seq_gset_split:Nnn \g_grill_acceptable_seq { , } { #1 }
}
\NewDocumentCommand{\ExamineFile}{mm}
{% #1 = input file, #2 = output file
\grill_examine_file:nn { #1 } { #2 }
}
\cs_new_protected:Npn \grill_examine_file:nn #1 #2
{
\ior_open:Nn \l_grill_input_stream { #1 }
\iow_open:Nn \l_grill_output_stream { #2 }
\ior_open:Nn \l_grill_input_stream { #1 }
\iow_open:Nn \l_grill_output_stream { #2 }
\regex_set:Nx \l__grill_acceptable_regex
{
\exp_not:n{\cB.}
(\seq_use:Nnnn \g_grill_acceptable_seq { | } { | } { | } )
\exp_not:n{\cE.}
}
\ior_map_inline:Nn \l_grill_input_stream
{ \__grill_lookup_line:n { ##1 } }
\iow_close:N \l_grill_output_stream
\ior_close:N \l_grill_input_stream
}
\cs_new_protected:Npn \__grill_lookup_line:n #1
{
%% Check if the prefix is present
\regex_match:NnT \g_grill_prefix_regex { #1 }
{
%% Check whether the value is not among the acceptable ones
\regex_match:NnF \l__grill_acceptable_regex { #1 }
{ \iow_now:Nn \l_grill_output_stream { #1 } }
}
}
\cs_generate_variant:Nn \regex_set:Nn { Nx }
\ExplSyntaxOff
\begin{document}
\SetAcceptableValues{AA,BB,CC}
\ExamineFile{FileA}{FileB}
\DTLloadrawdb[noheader,keys={Problem}]{MyDB}{FileB.tex}%
\DTLdisplaydb{MyDB}
\end{document}