O cenário: lendo uma data em um yyyy-mm-dd
formulário de um arquivo para um cs. Posteriormente, esse cs é comparado a uma macro de 'data atual' para gravar alguns argumentos de uma maneira específica em um arquivo externo. A macro do dia atual segue as linhas de
% \def\TODAY{}
% \def\Today{\the\year-\TwoDigits{\the\month}-\TwoDigits{\the\day} }
\def\TODAY{\xdef\Today{\the\year-\TwoDigits{\the\month}-\TwoDigits{\the\day}}}
Isso funciona para rotular coisas, pois \ref{yyyy-mm-dd}
funciona conforme o esperado. Não tendo nenhum extra \TODAY
e depois usando \def
'd Today, é a comparação que não está funcionando. etoolbox
's \ifstrequal
não é o que eu usei antes. Sempre que a data mudava eu usava um single \xdef
e depois passava essa macro para a \ifx
, e para que funcionasse tive que definir a data com um anexo.editarLeia, para minha surpresa, insere um único espaço depois de tudo o que foi lido.
Atualmente supostamente estou consertando as coisas, mas quebrei de alguma forma e agora não combina mais. O primeiro culpado foi que meu \TwoDigits
cmd era robusto, mudando-o de volta para \def
em vez de \NewDocumentCommand
corrigi-lo. O último é para comandos em nível de usuário, então deixarei isso escapar. Mas os resultados do mwe não são claros para mim.
0.txt
contém uma linha with 2001-01-01
e uma linha new depois, como se uma linha tivesse sido escrita nele e a saída tivesse sido fechada.
As questões:
- Qual é a maneira 'certa' de comparar coisas (macro, cs, comando?) que (deveria) expandir para strings?
- Por que não
\edef
,\xdef
trabalhe aqui, pensei que fosse uma expansão completa e, de fato, antes (meu controle de versão está quase ausente, então não posso dar a mínima para isso) funcionou. - Qual é o significado da robustez? Existe uma regra simples quando é necessário, obrigatório ou irrelevante?
- Está funcionando com
xstring
's\IfStrEqual
apenasse thefor inserido na definição de
\datemacro
, e não nos colchetes da comparação, ou seja,{\datemacro }
. Por que? \ifstrequal
supostamente não se expande - usei uma vez em um comando para testar se um argumento é igual a&
, isso funciona - o número 1 está se tornando o que foi inserido e não conta como uma expansão?
editar: esqueci \ifx
que era usado para macros, não para argumentos delimitados, desculpe.
Exemplo 1;
\documentclass{article}
\usepackage[top=1.5cm, bottom=0.6cm, hmargin=1.5cm]{geometry}
\usepackage{etoolbox}
\newread\periods
\openin\periods=0.txt
\begin{document}\setlength\parindent{0pt}\fontsize{20}{20}\selectfont
\def\testi{2001-01-01}
\edef\testii{2001-01-01}
\def\testiii{2001-01-01 }
\edef\testiiii{2001-01-01 }
\global\read\periods to \DDD
\ifstrequal{\testi}{2001-01-01}{T\\}{F\\}% F
\ifstrequal{\testii}{2001-01-01}{T\\}{F\\}% F
\ifstrequal{\testiii}{2001-01-01}{T\\}{F\\}% F
\ifstrequal{\testiiii}{2001-01-01}{T\\}{F\\}% F
\ifstrequal{\DDD}{2001-01-01}{T\\}{F\\}% F
\ifstrequal{\testi}{\DDD}{T\\}{F\\}% F
\ifstrequal{\testii}{\DDD}{T\\}{F\\}% F
\ifstrequal{\testiii}{\DDD}{T\\}{F\\}% F
\ifstrequal{\testiiii}{\DDD}{T\\}{F\\}% F
\ifstrequal{\DDD}{\DDD}{T\\}{F\\}% T
\ifx{\testi}{2001-01-01} T\\\else F\\\fi% F
\ifx{\testii}{2001-01-01} T\\\else F\\\fi% F
\ifx{\testiii}{2001-01-01} T\\\else F\\\fi% F
\ifx{\testiiii}{2001-01-01} T\\\else F\\\fi% F
\ifx{\DDD}{2001-01-01} T\\\else F\\\fi% F
\ifx{\testi}{\DDD} T\\\else F\\\fi% F
\ifx{\testii}{\DDD} T\\\else F\\\fi% F
\ifx{\testiii}{\DDD} T\\\else F\\\fi% F
\ifx{\testiiii}{\DDD} T\\\else F\\\fi% F
\ifx{\DDD}{\DDD} T\\\else F\\\fi% F
\ifcsequal{\testi}{\DDD}{T\\}{F\\}% F
\ifcsequal{\testii}{\DDD}{T\\}{F\\}% F
\ifcsequal{\testiii}{\DDD}{T\\}{F\\}% F
\ifcsequal{\testiiii}{\DDD}{T\\}{F\\}% F
\ifcsequal{\DDD}{\DDD}{T\\}{F\\}% F
\ifdefequal{\testi}{\DDD}{T\\}{F\\}% F
\ifdefequal{\testii}{\DDD}{T\\}{F\\}% F
\ifdefequal{\testiii}{\DDD}{T\\}{F\\}% T
\ifdefequal{\testiiii}{\DDD}{T\\}{F\\}% T
\ifdefequal{\DDD}{\DDD}{T\\}{F\\}% T
\end{document}
exemplo 2;
\documentclass{article}
\usepackage[top=1.5cm, bottom=0.6cm, hmargin=1.5cm]{geometry}
\usepackage{etoolbox,xstring}
\def\TwoDigits#1{\ifnum#1<10 0#1\else#1\fi}
\newcount\month
\month 1\relax
\newcount\day
\day 1\relax
\newread\periods
\openin\periods=0.txt
\global\read\periods to \DDD
\def\testi{2001-\TwoDigits{\the\month}-\TwoDigits{\the\day}}%
\edef\testii{2001-\TwoDigits{\the\month}-\TwoDigits{\the\day}}%
\def\testiii{2001-\TwoDigits{\the\month}-\TwoDigits{\the\day} }%
\edef\testiiii{2001-\TwoDigits{\the\month}-\TwoDigits{\the\day} }%
\begin{document}\setlength\parindent{0pt}
DDD is \DDD.% space between cs and .
\ifstrequal{\testi}{2001-01-01}{T\\}{F\\}% F
\ifstrequal{\testii}{2001-01-01}{T\\}{F\\}% F
\ifstrequal{\testiii}{2001-01-01}{T\\}{F\\}% F
\ifstrequal{\testiiii}{2001-01-01}{T\\}{F\\}% F
\ifstrequal{\DDD}{2001-01-01}{T\\}{F\\}% F
\ifstrequal{\testi}{\DDD}{T\\}{F\\}% F
\ifstrequal{\testii}{\DDD}{T\\}{F\\}% F
\ifstrequal{\testiii}{\DDD}{T\\}{F\\}% F
\ifstrequal{\testiiii}{\DDD}{T\\}{F\\}% F
\ifstrequal{\DDD}{\DDD}{T\\}{F\\}% T
\ifx\testi{2001-01-01} T\\\else F\\\fi% F
\ifx\testii{2001-01-01} T\\\else F\\\fi% F
\ifx\testiii{2001-01-01} T\\\else F\\\fi% F
\ifx\testiiii{2001-01-01} T\\\else F\\\fi% F
\ifx\DDD{2001-01-01} T\\\else F\\\fi% F
\ifx\testi\DDD T\\\else F\\\fi% F
\ifx\testii\DDD T\\\else F\\\fi% F
\ifx\testiii\DDD T\\\else F\\\fi% F
\ifx\testiiii\DDD T\\\else F\\\fi% T
\ifx\DDD\DDD T\\\else F\\\fi% T
\ifcsequal{\testi}{\DDD}{T\\}{F\\}% F
\ifcsequal{\testii}{\DDD}{T\\}{F\\}% F
\ifcsequal{\testiii}{\DDD}{T\\}{F\\}% F
\ifcsequal{\testiiii}{\DDD}{T\\}{F\\}% F
\ifcsequal{\DDD}{\DDD}{T\\}{F\\}% F
\ifdefequal{\testi}{\DDD}{T\\}{F\\}% F
\ifdefequal{\testii}{\DDD}{T\\}{F\\}% F
\ifdefequal{\testiii}{\DDD}{T\\}{F\\}% F
\ifdefequal{\testiiii}{\DDD}{T\\}{F\\}% T
\ifdefequal{\DDD}{\DDD}{T\\}{F\\}% T
\IfStrEq{\testi}{\DDD}{T\\}{F\\}% F
\IfStrEq{\testii}{\DDD}{T\\}{F\\}% F
\IfStrEq{\testi }{\DDD}{T\\}{F\\}% F
\IfStrEq{\testii }{\DDD}{T\\}{F\\}% F
\IfStrEq{\testiii}{\DDD}{T\\}{F\\}% T
\IfStrEq{\testiiii}{\DDD}{T\\}{F\\}% T
\IfStrEq{\DDD}{\DDD}{T\\}{F\\}% T
\end{document}
Responder1
\ifstrequal
Da documentação de etoolbox
:
\ifstrequal{⟨string⟩}{⟨string⟩}{⟨true⟩}{⟨false⟩}
Compara duas strings e executa ⟨true⟩ se forem iguais, e ⟨false⟩ caso contrário. As strings não são expandidas no teste e a comparação é independente do código de categoria. Os tokens de sequência de controle em qualquer um dos argumentos ⟨string⟩ serão destokenizados e tratados como strings. Este comando é robusto.
Portanto, \ifstrequal{\testi}{...}
não retornará verdadeiro, a menos que ...
seja exatamente igual a\testi
como cordas.
Por outro lado,
\expandafter\ifstrequal\expandafter{\DDD}{2001-01-01 }{T}{F}
retornará T
, mas observe o espaço de traling, que é gerado ao \read
ver um fim de linha.
\ifx
Esta é uma condicional primitiva e deve ser usada com sua sintaxe adequada: \ifx AB
compara os tokens A
e B
sem expansão. Então \ifx{\DDD}...
vou comparar {
com \DDD
.
\ifcsequal
\ifcsequal{⟨csname⟩}{⟨csname⟩}{⟨true⟩}{⟨false⟩}
Semelhante a,\ifdefequal
exceto que usa nomes de sequências de controle como argumentos.
Assim \ifcsequal{\testi}{\DDD}
, expandirá ambos \testi
e \DDD
, portanto, é o mesmo que fazer, \ifcsequal{2001-01-01}{2001-01-01 }
o que retorna falso porque as duas sequências de controle construídas são equivalentes a \relax
.
\ifdefequal
É aqui que você finalmente faz com que o código retorne verdadeiro. Observe que se você usar
\def\testiii{2001-\TwoDigits{\the\month}-\TwoDigits{\the\day} }%
então \ifdefequal{\testiii}{\DDD}
retornaráfalso, porque analisa apenas a expansão de primeiro nível. Por outro lado, a \edef
versão é o que funciona.
\IfStrEq
Isso expande totalmente seus argumentos (sob condições normais), portanto a comparação com \testiiii
ou \testiiii
funciona.
Robustez
A robustez de \ifstrequal
é completamente irrelevante. Bem, não completamente, na verdade. Se o seu mecanismo TeX suportar \expanded
(tudo será em algumas semanas, com o lançamento do TeX Live 2019), algo como
\expanded{\ifstrequal}{\testiii}{\DDD}{T}{F}}
retornará T
e a robustez \ifstrequal
é decisiva para que isso funcione.
Use o teste de trabalho.