
El siguiente código produce los resultados que deseo, que es una lista de líneas con XXX={<value>}
a <value>
que no está en la lista de valores permitidos:
Sin embargo, esta solución requiere que tenga la misma información en dos lugares, lo cual es muy propenso a errores. Entonces, ¿hay alguna manera de generar la secuencia de grep -v
macros en función del contenido de \ListOfAcceptableValues
.
Se me ocurre una solución de fuerza bruta es utilizar varios archivos para cada elemento de la lista de valores permitidos, pero creo que probablemente haya una forma más elegante de hacerlo.
Notas:
- Sólo necesito que funcione en MacOS, por lo que todas las utilidades de Unix están disponibles.
- Lo estoy usando
cat
aquí porque emula mejor el uso real de esta macro.
Código:
\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}
Respuesta1
\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
}
Respuesta2
Una solución pura de LaTeX (3); Sin embargo, los espacios iniciales no se conservan.
\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}
Otra solución que utiliza expresiones regulares; Lo agregué \XXX
como prefijo, como preguntaste en el comentario.
\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}