Stel dat ik een vloekwoord <word> zou willen censureren met grawlixes , bijv “Wat de # @ $! Ben je aan het doen ?!” Hoe kan ik een commando \censor zo definiëren dat \censor{<word>} resulteert in een reeks van deze symbolen? Ik weet niet helemaal zeker welke of hoeveel symbolen moeten worden gebruikt, gezien het woord <word>. Ik veronderstel dat het aantal gebruikte symbolen ongeveer gelijk moet zijn aan het aantal tekens in <word>.

Bedankt voor je input!

Opmerkingen

  • Het is veel gemakkelijker om dat in de teksteditor te doen dan in TeX. (luatex is waarschijnlijk gemakkelijker dan klassieke tex als je het echt op tekstniveau wilt doen) (Het is gemakkelijk genoeg om het in beperkte tekstcontexten te doen, maar moeilijk als je het in willekeurige alineas en lijsten enz. moet doen)
  • zie ook tex.stackexchange.com/questions/88394/…
  • @percusse I # @ $! &%? !% $ @!% $.
  • @GonzaloMedina Kan ik een klinker kopen?
  • Nou ja, tenminste Ik heb vandaag een nieuw woord geleerd. Maar waarom is niet ‘ t het meervoud grawlices ?

Antwoord

Een willekeurig symbool wordt uit een lijst gehaald en aan een tokenlijst toegevoegd; wanneer de breedte van de verzamelde symbolen meer is dan de breedte van het woord min 2pt, worden de symbolen afgedrukt, anders wordt er een ander symbool toegevoegd.

\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} 

voer de beschrijving van de afbeelding hier in

Antwoord

Een bescheiden poging met lualatex:

De vervangende code is erg naïef, we hebben iets robuuster nodig.

\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} 

De output:

Meer eenden

Moraal van het verhaal: Ik “ben vreselijk in het vertellen van verhalen. :)

Laten we nu de grawlixen toevoegen . Omdat ik een betere Lua-code nodig heb, maken we een extern bestand censor.lua en noem het vanuit .tex code:

\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} 

De uitvoer:

Grawlixes

Moraal van het nieuwe verhaal: door grawlixes aan een tekst toe te voegen, ziet het er ondeugend uit. :)

Reacties

  • +1 (hoewel ik hoopte een foto van een eend te zien, werd deze misschien gecensureerd?)

Answer

Afgezien van de voor- en nadelen van hoe en waarom je dit moet doen, vind ik het een leuke kleine oefening om te doen met xstring . Dus hier is mijn mening:

\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} 

Zoals je kunt zien, is de beperking dat de grawlix zal bestaan uit dezelfde set karakters, in dezelfde volgorde. (Je kunt de tekenset opnieuw definiëren of een manier vinden om ze willekeurig te maken bij elke aanroep van de macro … maar dat is “een ander verhaal! ;)) Maar je grawlix zal net zo lang zijn als het gecensureerde woord.

Wat er gebeurt, is dat xstring zijn eigen manieren heeft om argumenten uit te breiden en dat de macros niet kunnen worden genest. Het resultaat van de macro die vindt de lengte van het gecensureerde woord wordt geretourneerd in een andere macro (hier fantasierijk \result genoemd) die (her) gebruikt zal worden om de vooraf gedefinieerde \grawlix op de juiste plek.

De \expandarg macro zorgt ervoor dat de uitbreiding correct wordt uitgevoerd. Volgens xstring documentatie, staat het toe dat alle doorgegeven argumenten exact één keer worden uitgebreid. Daarom moet ervoor worden gezorgd dat groepen die een enkel teken vertegenwoordigen met accolades (bijv. het \sharp symbool leeft in wiskundige modus, maar we willen niet t de dollartekens die het afbakenen om als afzonderlijke tokens te worden gezien).

Opmerkingen

  • Ik don ‘ denk niet dat \makeatletter en \makeatother nodig zijn rond de @ … Het kan worden gebruikt als het symbool dat het meteen is.
  • @cgnieder Het ‘ is een goed werk, ze zijn niet nodig omdat ze helemaal geen effect hebben als ze binnen de definitie worden gebruikt zoals hier: – )
  • @DavidCarlisle waar, ik had niet ‘ daarover nagedacht … ik heb meer koffie nodig

Answer

Een eenvoudige TeX-oplossing zonder aanvullende pakketten, gebaseerd op ideeën van 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} 

U wilt waarschijnlijk dat het resultaat verband houdt met het gebruikte woord.In deze oplossing is het \lccode van een karakter modulo 7. Je kunt ofwel

 \fifo censored \ofif 

schrijven of, zoals voorgesteld (sorry voor mijn taalgebruik),

\censor{fuck} \censor{WORD} it is \censor{shit} 

verkrijgen

voer hier een afbeeldingbeschrijving in

Enkele verklaringen. De belangrijkste tool is de implementatie van de FIFO-wachtrij (First-In-First-Out) voorgesteld door Kees van der Laan:

\def\fifo#1{\ifx\ofif#1\ofif\fi \process#1\fifo} \def\ofif#1\fifo{\fi} 

De \fifo commando roept een macro \process op die de individuele argumenten afhandelt. Elk token wordt verwerkt tot \ofif.

De rest is eenvoudig. Door te manipuleren op de tellers \cur en \cura krijgen we een getal tussen 0 en 6 en \ifcase neemt verschillende censuur-tekens voor verschillende waarden.

Opmerking. Ik ben erg geïnteresseerd in de echte regels ( als ze bestaan) van het vervangen van vloekwoorden door strings van @ -achtige symbolen.

Reacties

  • Erg leuk. Kunt u misschien wat uitleggen (excuseer de woordspeling) hoe de code werkelijk werkt?
  • @AlanMunn Ja, maar na thuiskomst (laat op de avond).
  • \censor{MSWORD}

Antwoord

Een stabiele manier om symbolen uit te wisselen is door de lettertypecodering te wijzigen of om het lettertype opnieuw in te voeren. Een eenvoudig voorbeeld

\documentclass{article} \begin{document} \newcommand\censor[1]{\fontencoding{OMS}\selectfont #1} \censor{Censored} \end{document} 

Met lualatex zal het in de toekomst (wanneer de interface stabieler is) waarschijnlijk mogelijk zijn om virtuele opnieuw gecodeerde lettertypen te maken fly, momenteel zou het al mogelijk moeten zijn om het te doen met een feature-bestand.

Antwoord

Dit is een uitbreiding op @egreg “s antwoord met een ander antwoord door @egreg.

Met deze code kun je een hele zin invoeren in \censor en alle woorden die aanvankelijk aan een lijst zijn toegevoegd met \addcensor worden vervangen door grawlixes. Het argument voor \addcensor kan een enkel woord of een door kommas gescheiden lijst.

\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} 

voer een afbeeldingsbeschrijving in hier

Reacties

  • Het irriteert me wanneer je traditionele plaatsing of open en sluitende accolade (open accolade naast de functie, dan nieuwe regel, dan de code, en dan de sluitende accolade alleen in een nieuwe regel —zonder inspringing—), mengt het met de aanbevolen LaTeX3-manier (beide alleen op een nieuwe regel, evenveel ruimte ingesprongen).
  • @Manuel Sorry, Ik hoop dat mijn bijgewerkte antwoord past bij de aanbevolen stijl.
  • Zeker beter (IMO). Ik vind deze manier leuk, zelfs nu ik ‘ m de ConTeXt-broncode lees en het volledig anders schrijft (ze gebruiken tenminste ‘ geen de openingsaccolade, nieuwe regel, code, nieuwe regel sluitaccolade zonder al te veel inspringing, maar iets meer als %, nieuwe regel, openingsaccolade en code, meer code en sluitaccolade hierna naar de code).

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *