iv id =を使用して<word>
を使用して冒とく的な単語を検閲するとします。 “609e6f8c9b”>
grawlixes 、例: 「#@ $!何してるの?!」\censor{<word>}
がこれらの記号の文字列になるようにコマンド\censor
を定義するにはどうすればよいですか?<word>
という単語を指定すると、どの記号またはいくつの記号を使用する必要があるのか完全にはわかりません。使用する記号の数は、<word>
の文字数とほぼ同じであると思います。
ご入力いただきありがとうございます!
コメント
- TeXよりもテキストエディタソースで行う方がはるかに簡単です。 (luatexは、本当にテキストレベルで実行したい場合は、おそらく従来のtexよりも簡単です)(制限されたテキストコンテキストで実行するのは簡単ですが、任意の段落やリストなどで実行する必要がある場合は困難です)
- tex.stackexchange.com/questions/88394/ …
- @percusse I#@ $!&%? !%$ @!%$。
- @GonzaloMedina 母音を購入できますか?
- 少なくとも、今日、新しい単語を学びました。しかし、なぜ’複数の grawlices ではないのですか?
回答
ランダムな記号がリストから取得され、トークンリストに追加されます。累積された記号の幅が単語の幅から2ptを引いた値よりも大きい場合、記号が印刷されます。それ以外の場合は、別の記号が追加されます。
\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}
回答
:
置換コードは非常に単純なので、より堅牢なものが必要になります。
\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}
出力:
モラルストーリー:ストーリーを語るのがひどいです。:)
では、grawlixを追加しましょう。より良いLuaコードが必要なので、外部ファイルcensor.lua
を作成し、.tex
コードから呼び出します:
\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}
出力:
新しいストーリーのモラル:テキストにgrawlixを追加すると、いたずらに見えます。:)
コメント
- +1(アヒルの写真を見たかったのに、おそらく打ち切られたのでしょうか?)
回答
これを行う方法と理由の長所と短所は別として、 xstring
。これが私の見解です:
\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}
ご覧のとおり、制限は、grawlixが同じ文字セットで同じ順序で構成されることです。 (文字セットを再定義するか、マクロを呼び出すたびにランダム化する方法を見つけることができます…しかし、それは「別の話です!;)
)しかし、あなたのgrawlixは同じくらい長くなります検閲された単語として。
xstring
には引数を展開する独自の方法があり、マクロをネストすることはできません。打ち切られた単語の長さは、事前定義された\grawlix
を分割するために(再)使用される別のマクロ(ここでは\result
と想像的に呼ばれます)で返されます。 div>を適切な場所に配置します。
\expandarg
マクロは、展開が適切に行われることを確認します。xstring
によるとドキュメントでは、渡されたすべての引数を正確に一度展開できるようになります。したがって、中括弧で単一文字を表すグループを保護するように注意する必要があります(例:\sharp
シンボルはmathmodeに存在しますが、私たちは望んでいません個別のトークンとして表示されるように区切るドル記号)。
コメント
- 私は’
\makeatletter
と\makeatother
が@の周りに必要だとは思わない…すぐにシンボルとして使用できます。 - @cgnieder It ‘ここでの定義の内部で使用してもまったく効果がないため、必要ありません。 )
- @DavidCarlisle本当、私は’それについて考えていませんでした…もっとコーヒーが必要です
回答
Kees van derLaanのアイデアに基づく追加パッケージのないプレーンなTeXソリューション。
\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}
おそらく、使用されている単語に関連した結果が必要です。このソリューションでは、7を法とする文字の\lccode
です。
\fifo censored \ofif
または、提案どおりに記述できます。 (私の言語では申し訳ありません)、
\censor{fuck} \censor{WORD} it is \censor{shit}
取得
いくつかの説明。主なツールは、Kees van der Laanによって提案されたFIFO(First-In-First-Out)キューの実装です。
\def\fifo#1{\ifx\ofif#1\ofif\fi \process#1\fifo} \def\ofif#1\fifo{\fi}
\fifo
コマンドは、個々の引数を処理するマクロ\process
を呼び出します。すべてのトークンは、\ofif
まで処理されます。
残りは簡単です。カウンター\cur
と\cura
を操作すると、0から6までの数値と\ifcase
が得られます。値ごとに異なる検閲文字を使用します。
備考。実際のルールに非常に興味があります(ののしり言葉を@のような記号の文字列に置き換えること。
コメント
- とてもいい。コードが実際にどのように機能するかについて、少し拡張して(駄洒落を許して)いただけませんか?
- @AlanMunnはい、でも帰宅後(夕方)。
-
\censor{MSWORD}
回答
記号を交換する安定した方法は、フォントエンコーディングを変更することですまたはフォントを再エンコードします。簡単な例
\documentclass{article} \begin{document} \newcommand\censor[1]{\fontencoding{OMS}\selectfont #1} \censor{Censored} \end{document}
lualatexを使用すると、将来(インターフェイスがより安定したときに)仮想の再エンコードされたフォントをその場で作成できるようになります。飛ぶ、現在、機能ファイルでそれを行うことはすでに可能であるはずです。
回答
これは@egregの回答の拡張機能です @egregによる別の回答を使用します。
このコードを使用すると、および\addcensor
を使用してリストに最初に追加されたすべての単語はgrawlixesに置き換えられます。\addcensor
への引数は次のいずれかになります。単一の単語またはコンマ区切りのリスト。
\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}
コメント
- 従来のオープン配置を使用すると、イライラします閉じ中括弧(関数に隣接する開き中括弧、次に新しい行、次にコード、次に閉じ中括弧だけを新しい行にインデントなしで)、推奨されるLaTeX3の方法(両方とも新しい行に単独で)と混合します。同じ量のスペースをインデントします。
- @Manuel申し訳ありませんが、更新された回答が推奨されるスタイルに適合することを願っています。
- 間違いなく優れています(IMO)。私はこの方法が好きです。今でも’ ConTeXtソースコードを読んでいて、まったく異なる書き込みをしています(少なくとも’は使用していません)開始中括弧、改行、コード、インデントが多すぎない新しい行終了中括弧、ただし
%
、新しい行、開始中括弧とコード、その他のコード、次の終了中括弧のようなものコードに)。