iv id =를 사용하여 저주 단어 <word>
를 검열하고 싶다고 가정합니다. “609e6f8c9b”>
그롤 릭스 , 예 : “# @ $! 뭐하는거야?!”\censor{<word>}
가 이러한 기호의 문자열이되도록 명령\censor
를 어떻게 정의 할 수 있습니까?<word>
라는 단어에 어떤 기호를 사용해야하는지 또는 몇 개를 사용해야하는지 잘 모르겠습니다. 사용 된 기호의 수가<word>
의 문자 수와 거의 같아야한다고 생각합니다.
입력 해 주셔서 감사합니다!
댓글
- Tex보다 텍스트 편집기 소스에서하는 것이 훨씬 더 쉽습니다. (루아 텍스는 텍스트 수준에서 정말로하고 싶다면 클래식 텍스보다 쉬울 것입니다.) (제한된 텍스트 컨텍스트에서 할 수있을만큼 쉽지만 임의의 단락과 목록 등에서해야하는 경우에는 어렵습니다)
- tex.stackexchange.com/questions/88394/ …
- @percusse I # @ $! & %? ! % $ @! % $.
- @GonzaloMedina 모음을 살 수 있나요?
- 글쎄요, 적어도 오늘 새로운 단어 를 배웠습니다. 하지만 ‘ 복수 그 롤리스 가 아닌 이유는 무엇입니까?
Answer
목록에서 임의의 기호를 가져와 토큰 목록에 추가합니다. 누적 된 기호의 너비가 단어 너비에서 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
기호가 수학 모드에 있지만 우리는 원치 않습니다. t를 구분하는 달러 기호는 별도의 토큰으로 표시됨).
댓글
- 나는하지 않습니다. ‘ @ 주위에
\makeatletter
및\makeatother
가 필요하다고 생각하지 않습니다 … 바로 기호로 사용할 수 있습니다.
li>
Answer
Kes van der Laan의 아이디어를 기반으로 한 추가 패키지가없는 일반 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를 사용하면 향후 (인터페이스가 더 안정적 일 때) 가상 재 코드 글꼴을 만들 수있을 것입니다. 지금은 이미 기능 파일을 사용하여 수행 할 수 있습니다.
Answer
@egreg “s answer @egreg의 다른 answer 를 사용합니다.
이 코드를 사용하면 및 \addcensor
를 사용하여 목록에 처음 추가 된 모든 단어는 grawlix로 대체됩니다. \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 소스 코드를 읽고 완전히 다른 방식으로 작성합니다 (적어도 ‘ 여는 중괄호, 새 줄, 코드, 들여 쓰기가없는 줄 바꿈 닫는 중괄호,하지만
%
, 새 줄, 여는 중괄호 및 코드, 추가 코드, 닫는 중괄호 다음 코드).