Angenommen, ich möchte ein Schimpfwort <word>
mit Grawlixe , z „Was zum Teufel machst du?!“ Wie kann ich einen Befehl \censor
so definieren, dass \censor{<word>}
zu einer Zeichenfolge dieser Symbole führt? Ich bin mir nicht ganz sicher, welche oder wie viele Symbole angesichts des Wortes <word>
verwendet werden sollen. Ich nehme an, dass die Anzahl der verwendeten Symbole ungefähr der Anzahl der Zeichen in <word>
entsprechen sollte.
Vielen Dank für Ihre Eingabe!
Kommentare
- Es ist viel einfacher, dies in der Texteditorquelle als in TeX zu tun. (Luatex ist wahrscheinlich einfacher als klassisches Tex, wenn Sie es wirklich auf Textebene ausführen möchten.) (Es ist einfach genug, es in eingeschränkten Textkontexten auszuführen, aber schwierig, wenn Sie es in beliebigen Absätzen und Listen usw. ausführen müssen.)
- siehe auch tex.stackexchange.com/questions/88394/…
- @percusse I # @ $! &%? !% $ @!% $.
- @GonzaloMedina Kann ich einen Vokal kaufen?
- Nun, zumindest Ich habe heute ein neues Wort gelernt. Aber warum ist ‚ nicht der Plural grawlices ?
Antwort
Ein zufälliges Symbol wird aus einer Liste entnommen und an eine Token-Liste angehängt. Wenn die Breite der akkumulierten Symbole größer als die Breite des Wortes minus 2pt ist, werden die Symbole gedruckt, andernfalls wird ein anderes Symbol angehängt.
\documentclass{article} \usepackage{xparse,pgf} \ExplSyntaxOn \NewDocumentCommand{\censor}{m} { \pointer_censor:n { #1 } } \seq_new:N \g_pointer_grawlixes_seq \tl_map_inline:nn { @ * \# ! \$ \% ? ! \# @ \% *} { \seq_gput_right:Nn \g_pointer_grawlixes_seq { #1 } } \int_const:Nn \c_pointer_grawlix_list_int { \seq_count:N \g_pointer_grawlixes_seq } \dim_new:N \l_pointer_censor_dim \dim_new:N \l_pointer_try_dim \box_new:N \l_pointer_censor_box \tl_new:N \l_pointer_grawlixes_tl \cs_new_protected:Npn \pointer_censor:n #1 { \tl_clear:N \l_pointer_grawlixes_tl \hbox_set:Nn \l_pointer_censor_box { #1 } \dim_set:Nn \l_pointer_censor_dim { \box_wd:N \l_pointer_censor_box } \pointer_add_grawlix: } \cs_new_protected:Npn \pointer_add_grawlix: { \hbox_set:Nn \l_pointer_censor_box { \l_pointer_grawlixes_tl } \dim_compare:nTF { \l_pointer_censor_dim - 2pt < \box_wd:N \l_pointer_censor_box } { \tl_use:N \l_pointer_grawlixes_tl } { \pgfmathparse{random(1,\int_eval:n {\c_pointer_grawlix_list_int})} \tl_put_right:Nx \l_pointer_grawlixes_tl { \seq_item:Nn \g_pointer_grawlixes_seq { \pgfmathresult } } \pointer_add_grawlix: } } \ExplSyntaxOff \begin{document} Censored \censor{Censored} \end{document}
Antwort
Ein bescheidener Versuch mit lualatex
:
Der Ersatzcode ist sehr naiv, wir würden etwas Robusteres benötigen.
\documentclass{article} \directlua{ % my list of bad words bad_words = { "fish", "cat", "dog", "horse", "alligator" } % the replacement string replacement = "duck" % a replacement function which returns % both the altered line and the number % of occurrences function replace(line) for _, element in pairs(bad_words) do if string.find(line, element) then return string.gsub(line, element, replacement) end end return line, 0 end % my "naive" censor function, it simply % replaces any occurrences of the % list of bad words by the replacement % string function censor(line) occurrences = 0 repeat line, occurrences = replace(line) until occurrences == 0 return line end % add the hook callback.register("process_input_buffer", censor)} \begin{document} Once upon a time, there was a little cat who lived inside an igloo. Don"t ask me what he was doing there. One day, the cat was visited by his two other friends, the dog and the alligator! --- ``What are you guys doing here?"", said the cat. --- ``We came to visit you, mr.\ cat!"", said the dog. --- ``Our friend horse will be late, he went to the store to buy some frozen fish for you``, replied the alligator. \end{document}
Die Ausgabe:
Moral von die Geschichte: Ich bin schrecklich darin, Geschichten zu erzählen. :)
Nun fügen wir die Grawlixe hinzu . Da ich einen besseren Lua-Code benötige, erstellen wir eine externe Datei censor.lua
und rufen sie aus unserem .tex
-Code auf:
\begin{filecontents*}{censor.lua} -- a list of symbols to represent the -- grawlixe symbols -- note that we need to escape -- some chars grawlixe_symbols = { "\\$", "\\#", "@", "!", "*", "\\&" } -- generate a grawlixe of length s -- note that the seed is not so random, so -- same values of s might get the same -- grawlixe pattern (I could add another seed -- mid code, but I"m lazy) function grawlixe(s) math.randomseed(os.time()) local u = table.getn(grawlixe_symbols) local i = math.random(u) local r = grawlixe_symbols[i] local current local w = 1 repeat current = math.random(u) while current == i do current = math.random(u) end i = current r = r .. grawlixe_symbols[i] w = w + 1 until w == s return r end -- a list of bad words to be censored bad_words = { "fish", "cat", "dog", "horse", "alligator" } -- our replacement function, it returns -- the new line and the number of -- replacements made -- note that this is a very naive replacement -- function, there"s a lot of room for -- improvement function replace(line) for _, element in pairs(bad_words) do if string.find(line, element) then return string.gsub(line, element, grawlixe(string.len(element))) end end return line, 0 end -- the censor function, it repeats -- ad nauseam until the line has -- nothing more to be censored function censor(line) local occurrences = 0 repeat line, occurrences = replace(line) until occurrences == 0 return line end -- register the callback callback.register("process_input_buffer", censor) \end{filecontents*} \documentclass{article} \directlua{dofile("censor.lua")} \begin{document} Once upon a time, there was a little cat who lived inside an igloo. Don"t ask me what he was doing there. One day, the cat was visited by his two other friends, the dog and the alligator! --- ``What are you guys doing here?"", said the cat. --- ``We came to visit you, mr.\ cat!"", said the dog. --- ``Our friend horse will be late, he went to the store to buy some frozen fish for you``, replied the alligator. \end{document}
Die Ausgabe:
Moral der neuen Geschichte: Wenn Sie einem Text Grawlixe hinzufügen, sieht er ungezogen aus. :)
Kommentare
- +1 (obwohl ich gehofft hatte, ein Entenbild zu sehen, wurde es vielleicht zensiert?)
Antwort
Abgesehen von den Vor- und Nachteilen, wie und warum dies zu tun ist, finde ich es eine nette kleine Übung, die mit xstring
. Hier ist meine Meinung dazu:
\documentclass{article} \usepackage{xstring} \def\grawlix{{\makeatletter@\makeatother}\textdollar{$\sharp$}*?!} \newcommand{\censor}[1]{\StrLen{#1}[\result]% \expandarg\StrLeft{\grawlix}{\result}[]} \begin{document} What the \censor{word} is this??? \end{document}
Wie Sie sehen können, besteht die Einschränkung darin, dass die Grawlix aus demselben Zeichensatz in derselben Reihenfolge besteht. (Sie können den Zeichensatz neu definieren oder einen Weg finden, sie bei jedem Aufruf des Makros zufällig zu sortieren … aber das ist eine andere Geschichte! ;)
) Aber Ihr Grawlix wird genauso lang sein als zensiertes Wort.
Was passiert ist, dass xstring
seine eigenen Möglichkeiten zum Erweitern von Argumenten hat und die Makros nicht verschachtelt werden können. Das Ergebnis des gefundenen Makros Die Länge des zensierten Wortes wird in einem anderen Makro (hier fantasievoll \result
genannt) zurückgegeben, das (erneut) zum Teilen des vordefinierten \grawlix
an der richtigen Stelle.
Das Makro \expandarg
stellt sicher, dass die Erweiterung ordnungsgemäß durchgeführt wird. Gemäß xstring
In der Dokumentation können alle übergebenen Argumente genau einmal erweitert werden. Daher muss darauf geachtet werden, Gruppen zu schützen, die ein einzelnes Zeichen mit geschweiften Klammern darstellen (z. B. die \sharp
Symbol lebt im Mathematikmodus, aber wir wollen nicht t die Dollarzeichen, die es abgrenzen, um als separate Token angesehen zu werden).
Kommentare
- Ich ‚ Ich glaube nicht, dass
\makeatletter
und\makeatother
um das @ … erforderlich sind. Es kann sofort als Symbol verwendet werden. - @cgnieder Es ‚ ist eine gute Arbeit, sie sind nicht notwendig, da sie überhaupt keine Wirkung haben, wenn sie innerhalb der Definition wie hier verwendet werden: – )
- @DavidCarlisle wahr, ich hatte ‚ nicht darüber nachgedacht … Ich brauche mehr Kaffee
Antwort
Eine einfache TeX-Lösung ohne zusätzliche Pakete, basierend auf den Ideen von Kees van der Laan.
\documentclass{article} \begin{document} \newcount\cur \newcount\cura \def\fifo#1{\ifx\ofif#1\ofif\fi \process#1\fifo} \def\ofif#1\fifo{\fi} \def\mynum#1{\cur\the\lccode`#1\relax\the\cur } \def\process#1{\cur\the\lccode`#1\relax\cura\cur \divide\cura by7 \multiply\cura by7 \advance\cur by-\cura\ifcase\cur!\or@\or\#\or\$\or\%\or\&\or*\else ERROR\fi } \fifo censored \ofif \bigskip \def\censor#1{\fifo #1\ofif} \censor{fuck} \censor{WORD} it is \censor{shit} \end{document}
Sie möchten wahrscheinlich, dass das Ergebnis mit dem verwendeten Wort verknüpft wird.In dieser Lösung ist es \lccode
eines Zeichenmoduls 7. Sie können entweder
\fifo censored \ofif
oder wie vorgeschlagen schreiben (Entschuldigung für meine Sprache),
\censor{fuck} \censor{WORD} it is \censor{shit}
Erhalten
Einige Erklärungen. Das Hauptwerkzeug ist die von Kees van der Laan vorgeschlagene Implementierung der FIFO-Warteschlange (First-In-First-Out):
\def\fifo#1{\ifx\ofif#1\ofif\fi \process#1\fifo} \def\ofif#1\fifo{\fi}
Die ruft ein Makro \process
auf, das die einzelnen Argumente verarbeitet. Jedes Token wird verarbeitet, bis \ofif
.
Der Rest ist einfach. Durch Manipulieren der Zähler \cur
und \cura
erhalten wir eine Zahl zwischen 0 und 6 und \ifcase
nimmt unterschiedliche Zensurzeichen für unterschiedliche Werte an.
Bemerkung. Ich bin sehr an den tatsächlichen Regeln interessiert ( falls vorhanden), um Schimpfwörter durch Zeichenfolgen von @ -ähnlichen Symbolen zu ersetzen.
Kommentare
- Sehr schön. Könnten Sie vielleicht etwas näher erläutern (entschuldigen Sie das Wortspiel), wie der Code tatsächlich funktioniert?
- @AlanMunn Ja, aber nach der Rückkehr nach Hause (am späten Abend).
-
\censor{MSWORD}
Antwort
Eine stabile Möglichkeit zum Austauschen von Symbolen besteht darin, die Schriftartencodierung zu ändern oder um die Schriftart neu zu codieren. Ein einfaches Beispiel
\documentclass{article} \begin{document} \newcommand\censor[1]{\fontencoding{OMS}\selectfont #1} \censor{Censored} \end{document}
Mit lualatex wird es in Zukunft (wenn die Schnittstelle stabiler ist) wahrscheinlich möglich sein, virtuell neu codierte Schriftarten auf dem Bildschirm zu erstellen. fliegen, derzeit sollte es bereits möglich sein, dies mit einer Feature-Datei zu tun.
Antwort
Dies ist eine Erweiterung von @egregs Antwort Verwenden einer anderen Antwort von @egreg.
Mit diesem Code können Sie einen ganzen Satz in und alle Wörter, die ursprünglich mit \addcensor
zu einer Liste hinzugefügt wurden, werden durch Grawlixe ersetzt. Das Argument für \addcensor
kann entweder a sein einzelnes Wort oder eine durch Kommas getrennte Liste.
\documentclass{article} \usepackage{xparse,pgf} \ExplSyntaxOn \NewDocumentCommand{\censor}{m} { \pointer_badseq:n { #1 } } \tl_new:N \g_pointer_badwords_tl \NewDocumentCommand{\addcensor}{m} { \clist_map_inline:nn { #1 } { \tl_gput_right:Nn \g_pointer_badwords_tl { {##1}{} } } } \cs_generate_variant:Nn \str_case:nnTF { nV } \cs_new_protected:Npn \pointer_badseq:n #1 { \seq_set_split:Nnn \l_tmpa_seq { ~ } { #1 } \seq_map_inline:Nn \l_tmpa_seq { \str_case:nVTF { ##1 } \g_pointer_badwords_tl { \pointer_censor:n { ##1 } } { ##1 } ~ % Readd space } \tex_unskip:D % Remove the trailing space } % From @egreg"s answer \seq_new:N \g_pointer_grawlixes_seq \tl_map_inline:nn { @ * \# ! \$ \% ? ! \# @ \% *} { \seq_gput_right:Nn \g_pointer_grawlixes_seq { #1 } } \int_const:Nn \c_pointer_grawlix_list_int { \seq_count:N \g_pointer_grawlixes_seq } \dim_new:N \l_pointer_censor_dim \dim_new:N \l_pointer_try_dim \box_new:N \l_pointer_censor_box \tl_new:N \l_pointer_grawlixes_tl \cs_new_protected:Npn \pointer_censor:n #1 { \tl_clear:N \l_pointer_grawlixes_tl \hbox_set:Nn \l_pointer_censor_box { #1 } \dim_set:Nn \l_pointer_censor_dim { \box_wd:N \l_pointer_censor_box } \pointer_add_grawlix: } \cs_new_protected:Npn \pointer_add_grawlix: { \hbox_set:Nn \l_pointer_censor_box { \l_pointer_grawlixes_tl } \dim_compare:nTF { \l_pointer_censor_dim - 2pt < \box_wd:N \l_pointer_censor_box } { \tl_use:N \l_pointer_grawlixes_tl } { \pgfmathparse{random(1,\int_eval:n {\c_pointer_grawlix_list_int})} \tl_put_right:Nx \l_pointer_grawlixes_tl { \seq_item:Nn \g_pointer_grawlixes_seq { \pgfmathresult } } \pointer_add_grawlix: } } \ExplSyntaxOff \addcensor{censored,duck} \addcensor{street} \begin{document} A censored man walk down the street together with his duck. \censor{A censored man walk down the street together with his duck}. \end{document}
Kommentare
- Es ärgert mich, wenn Sie die traditionelle Platzierung von open verwenden und schließende Klammer (offene Klammer neben der Funktion, dann neue Zeile, dann der Code und dann die schließende Klammer allein in einer neuen Zeile – ohne Einzug -), wobei sie mit der empfohlenen LaTeX3-Methode gemischt wird (beide allein in einer neuen Zeile, eingerückt die gleiche Menge an Speicherplatz).
- @Manuel Sorry, Ich hoffe, meine aktualisierte Antwort passt zum empfohlenen Stil.
- Auf jeden Fall besser (IMO). Ich mag diese Art und Weise, auch jetzt, wo ich ‚ ConTeXt-Quellcode lese und er völlig anders schreibt (zumindest verwenden sie ‚ nicht die öffnende Klammer, neue Zeile, Code, neue Zeile schließende Klammer ohne Einrückung zu viel, aber eher
%
, neue Zeile, öffnende Klammer und Code, mehr Code und schließende Klammer als nächstes zum Code).