Anta at jeg vil sensurere et forbannelsesord <word> ved å bruke grawlixes , f.eks «Hva # @ $! Gjør du ?!» Hvordan kan jeg definere en kommando \censor slik at \censor{<word>} resulterer i en streng av disse symbolene? Jeg er ikke helt sikker på hvilke eller hvor mange symboler som skal brukes gitt ordet <word>. Jeg antar at antall symboler som brukes, tilnærmet tilsvarer antall tegn i <word>.

Takk for innspillet!

Kommentarer

  • Det er mye lettere å gjøre det i tekstredigerings kilden enn i TeX. (luatex er sannsynligvis enklere enn klassisk tex hvis du virkelig vil gjøre det på tekstnivå) (Det er lett nok å gjøre det i begrensede tekstkontekster, men vanskelig hvis du trenger å gjøre det i vilkårlige avsnitt og lister osv.)
  • se også tex.stackexchange.com/questions/88394/…
  • @percusse I # @ $! &%? !% $ @!% $.
  • @GonzaloMedina Kan jeg kjøpe vokal?
  • Vel, i det minste Jeg lærte et nytt ord i dag. Men hvorfor er ikke ‘ t flertall grawlices ?

Svar

Et tilfeldig symbol er hentet fra en liste og lagt til en tokenliste; når bredden på de akkumulerte symbolene er mer enn bredden på ordet minus 2pt, blir symbolene skrevet ut, ellers legges det til et annet symbol.

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

skriv inn bildebeskrivelse her

Svar

Et ydmykt forsøk med lualatex:

Erstatningskoden er veldig naiv, vi trenger noe mer robust.

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

Utgangen:

Flere ender

Moral av historien: Jeg er forferdelig i å fortelle historier. :)

La oss nå legge til grawlixene . Siden jeg trenger en bedre Lua-kode, la oss opprette en ekstern fil censor.lua og kalle den fra .tex kode:

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

Utgangen:

Grawlixes

Moralen til den nye historien: å legge til grawlixes i en tekst gjør at den ser slem ut. :)

Kommentarer

  • +1 (selv om jeg håpet å se et andebilde, kanskje det ble sensurert?)

Svar

Når vi ser bort fra fordeler og ulemper med hvordan og hvorfor du gjør dette, synes jeg det er en fin liten øvelse å gjøre med xstring . Så her tar jeg det:

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

Som du kan se, er begrensningen at grawlix vil være sammensatt av samme sett med tegn, i samme rekkefølge. (Du kan omdefinere tegnsettet eller finne en måte å randomisere dem ved hver påkallelse av makroen … men det «en annen historie! ;)) Men grawlixen din vil være like lang som det sensurerte ordet.

Det som skjer er at xstring har sine egne måter å utvide argumenter på, og makroene kan ikke nestes. Så resultatet fra makroen som finner lengden på det sensurerte ordet returneres i en annen makro (fantasifullt kalt her \result) som skal (re) brukes til å dele den forhåndsdefinerte \grawlix på rett sted.

\expandarg makroen sørger for at utvidelsen gjøres riktig. I henhold til xstring dokumentasjon, vil det tillate at alle argumenter som sendes utvides nøyaktig en gang. Derfor må det tas hensyn til å beskytte grupper som representerer et enkelt tegn med parenteser (f.eks. \sharp symbol bor i mathmode, men vi vil ikke t dollartegnene som avgrenser det for å bli sett på som separate tokens).

Kommentarer

  • Jeg don ‘ t tror \makeatletter og \makeatother er nødvendige rundt @ … Det kan brukes som symbolet det er med en gang.
  • @cgnieder Det ‘ en god jobb, de er ikke nødvendige, da de ikke har noen effekt i det hele tatt hvis de brukes inne definisjonen som her: – )
  • @ DavidCarlisle sant, jeg hadde ikke ‘ ikke tenkt på det … Jeg trenger mer kaffe

Svar

En vanlig TeX-løsning uten tilleggspakker, basert på ideer fra 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} 

Du vil sannsynligvis ha resultatet knyttet til ordet som brukes.I denne løsningen er det \lccode med et tegnmodul 7. Du kan skrive enten

 \fifo censored \ofif 

eller, som foreslått (beklager språket mitt),

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

får

skriv inn bildebeskrivelse her

Noen forklaringer. Hovedverktøyet er implantering av FIFO-kø (First-In-First-Out) foreslått av Kees van der Laan:

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

\fifo -kommandoen kaller en makro \process som håndterer de enkelte argumentene. Hvert token blir behandlet til \ofif.

Resten er enkel. Ved å manipulere på tellerne \cur og \cura får vi et tall mellom 0 og 6 og \ifcase tar forskjellige sensurtegn for forskjellige verdier.

Merknad. Jeg er veldig interessert i de virkelige reglene ( hvis de eksisterer) for å erstatte forbannelsesord med strenger med @ -lignende symboler.

Kommentarer

  • Veldig hyggelig. Kan du kanskje utvide (tilgi ordspillet) litt om hvordan koden faktisk fungerer?
  • @AlanMunn Ja, men etter å ha kommet hjem (sent på kvelden).
  • \censor{MSWORD}

Svar

En stabil måte å utveksle symboler på er å endre fontkoding eller for å kode koden på nytt. Et enkelt eksempel

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

Med lualatex vil det i fremtiden (når grensesnittet er mer stabilt) muligens være mulig å lage virtuelle re-kodede skrifter på-the- fly, for øyeblikket bør det allerede være mulig å gjøre det med en funksjonsfil.

Svar

Dette er en utvidelse av @egreg «s svar ved å bruke et annet svar av @egreg.

Med denne koden kan du skrive inn en hel setning i \censor og alle ord som opprinnelig ble lagt til i en liste med \addcensor erstattes av grawlixes. Argumentet for \addcensor kan være enten enkelt ord eller en kommaseparert 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} 

skriv inn bildebeskrivelse her

Kommentarer

  • Det irriterer meg når du bruker tradisjonell plassering av åpen og lukkestag (åpen stag ved siden av funksjonen, deretter ny linje, deretter koden og deretter stengebåndet alene i en ny linje – uten innrykk -), og blander den med den anbefalte LaTeX3-måten (begge alene på en ny linje, innrykket samme mengde plass).
  • @Manuel Beklager, Jeg håper mitt oppdaterte svar passer til den anbefalte stilen.
  • Definitly better (IMO). Jeg liker denne måten, selv nå som jeg ‘ leser ConTeXt-kildekoden og den skriver helt annerledes (i det minste bruker de ikke ‘ åpningsbøylen, ny linje, kode, ny stengebånd uten innrykk for mye, men noe mer som %, ny linje, åpningsbøyle og kode, mer kode, og lukkende bøyle neste til koden).

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert. Obligatoriske felt er merket med *