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} 

Bildbeschreibung hier eingeben

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:

Weitere Enten

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:

Grawlixes

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

Geben Sie hier die Bildbeschreibung ein

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} 

Geben Sie die Bildbeschreibung ein hier

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).

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.