替换现有文档中的某些分隔符:将 P( ) 替换为 P

替换现有文档中的某些分隔符:将 P( ) 替换为 P

\mathbb{P}在很长的现有文件中自动替换概率测度的分隔符的最佳策略是什么。

假设现有的 LaTeX 文件使用像\mathbb{P}(A)\mathbb{P}(B)和 这样的符号\mathbb{P}(...),但它应该使用符号\mathbb{P}\lbrack ...\rbrack

我猜很多 LaTeX 用户都面临着这类问题,但也许可以在 LaTeX 之外更好地解决它——也许通过在代码编辑器中使用正则表达式?(我对正则表达式的经验很少。)

重要的是,并非所有圆括号都应被替换。只有紧随其后的左括号\mathbb{P}和其对应的右括号才应被替换为方括号。

如果间隔的概率能够起作用,那就太好了 - 例如\mathbb{P}(\lbrack a, b))\mathbb{P}\lbrack\lbrack a, b)\rbrack但如果有百分之一的替换是错误的,它仍然会有所帮助。

PS:当然,最好首先定义一个命令,比如\newcommand{\PP}[1]{\mathbb{P}\left\lbrack{#1}\right\rbrack},但我正在谈论一个\mathbb{P}(...)在文本中硬编码的现有文档。

备注MWE:

\documentclass{article}
\usepackage{amssymb}

\begin{document}
    Basic examples: $\mathbb{P}(A)$,
    nested: $\mathbb{P}(A\cup(A\cap B))$, intervall-notation: $\mathbb{P}(X\in[a,b))$,
    left/right: $\mathbb{P}\left(X\in\left[a,(-b)^k\right)\right)$
    $\mathbb{P} ... (these\ parenthesis\ should\ not\ be\ affacted)$.%because they are not directly after P.

    Often $($ and $]$ are matched---e.g.: 
    $\mathbb{P}(X\in[a,\infty))$,
    $\mathbb{P}\left( Y\in[b,c)\cup[d,e)\right)$ and often $[$ and $)$ are matched---e.g.:
    $\mathbb{P}\left( Y\in[b,c)\cup(d,e]\right)$

    Sometimes \texttt{left} and \texttt{right} are used and sometimes not. %\left and \right
    And nesting can be quite deep.
    \[\mathbb{P}\left( X\in \left( [a,b)\cup\left(c,3\left(a+(-1)^k(d+e)\right)\right] \right)\setminus (B\cap ( \lbrack k,k+1) \cup C )) \right)\]
    There could be comments involved too:
    \[\mathbb{P}( X\in \left( [a,b)\cup\left(c,3\left(a+(-1)(d+e)\right)\right] \right)\setminus (B\cap ( \lbrack k,k+1)%k+2)
    \cup C )) )\]
\end{document}

答案1

一个简单的搜索/替换就是用 替换\mathbb{P}(\PP{P}(然后,假设所有\mathbb{P}都是以下形式,则\mathbb{P}(...)应该有效:

在此处输入图片描述

如果 中的内容()也有圆括号,则需要{}在其周围添加一个额外的 。也就是说,像 这样的内容\PP{P}({AB))需要更改为\PP{P}({(AB)})

\documentclass{article}
\usepackage{amssymb}

\newcommand*{\PP}{}% Ensure we are not overwriting an existing macro
\def\PP#1(#2){\mathbb{#1}[#2]}

\begin{document}
    %$\mathbb{P}(A)$% Replaced "\mathbb{P}" with "\PP{P}"
    $\PP{P}(A)$
\end{document}

答案2

只有紧接着的左括号\mathbb{P}和其对应的右括号应该被方括号替换。

这是一个基于 LuaLaTeX 的解决方案。它由 (a) 一个 Lua 函数组成,paren2brack该函数使用 Lua 的强大string.gsub功能;(b) 两个 LaTeX 实用宏(称为\ParenBrackOn\ParenBrackOff),用于打开和关闭 Lua 函数。括号到方括号的替换是“即时”执行的,即 tex 文件本身不会被编辑或修改。

该解决方案不仅可以处理\mathbb{P};事实上,的参数\mathbb可以是任何大写字母。

附录:我在 Lua 函数中添加了第二个string.gsub操作,以便它可以处理诸如此类的情况\mathbb{P}\left(A\right)

在此处输入图片描述

% !TEX TS-program = lualatex
\documentclass{article}
\usepackage{amssymb} % for '\mathbb' macro
\usepackage{luacode} % for 'luacode' env.

\begin{luacode}
function paren2brack ( s )
  s = s:gsub( "(\\mathbb{%u})(%b())" , function ( x , y )
                  return x .. "[" .. y:sub(2,-2) .. "]"
              end )
  s = s:gsub( "(\\mathbb{%u})\\left%((.-)\\right%)" , function ( x , y ) 
                  return x .. "\\left[" .. y .. "\\right]" 
              end )     
  return s 
end
\end{luacode}

%% Define a couple of LaTeX utility macros:
\newcommand\ParenBrackOn{\directlua{luatexbase.add_to_callback ( 
   "process_input_buffer" , paren2brack , "paren2brack" )}}
\newcommand\ParenBrackOff{\directlua{luatexbase.remove_from_callback ( 
   "process_input_buffer" , "paren2brack" )}}

\begin{document}

$\mathbb{P}(A)$, $\mathbb{Q}(B\cup(C\cap D))$, $\mathbb{P}\left(E\right)$  
--- Lua function not activated

\ParenBrackOn % assign the Lua function to LuaTeX's 'process_input_buffer' callback
$\mathbb{P}(A)$, $\mathbb{Q}(B\cup(C\cap D))$, $\mathbb{P}\left(E\right)$ 
--- Lua function is activated

\end{document}

答案3

匹配嵌套的括号/方括号并不是一件容易的事;我建议使用以下正则表达式插入perlvialatexindent及其 yaml 接口。没有什么可以阻止您将其合并到您自己的perl脚本中。

我用来生成输出的命令是

latexindent -rr -l=jakob.yaml myfile.tex -o=output.tex

输出.tex



\documentclass{article}
\usepackage{amssymb}

\begin{document}
    Basic examples: $\mathbb{P}\left\lbrack A\right\rbrack$,
    nested: $\mathbb{P}\left\lbrack A\cup(A\cap B)\right\rbrack$, intervall-notation: $\mathbb{P}\left\lbrack X\in[a,b)\right\rbrack$,
    left/right: $\mathbb{P}\left\lbrack X\in\left[a,(-b)^k\right)\right\rbrack$
    $\mathbb{P} ... (these\ parenthesis\ should\ not\ be\ affacted)$.%because they are not directly after P.

    Often $($ and $]$ are matched---e.g.: 
    $\mathbb{P}\left\lbrack X\in[a,\infty)\right\rbrack$,
    $\mathbb{P}\left\lbrack  Y\in[b,c)\cup[d,e)\right\rbrack$ and often $[$ and $)$ are matched---e.g.:
    $\mathbb{P}\left\lbrack  Y\in[b,c)\cup(d,e]\right\rbrack$

    Sometimes \texttt{left} and \texttt{right} are used and sometimes not. %\left and \right
    And nesting can be quite deep.
    \[\mathbb{P}\left\lbrack  X\in \left( [a,b)\cup\left(c,3\left(a+(-1)^k(d+e)\right)\right] \right)\setminus (B\cap ( \lbrack k,k+1) \cup C )) \right\rbrack\]
    There could be comments involved too:
    \[\mathbb{P}\left\lbrack  X\in \left( [a,b)\cup\left(c,3\left(a+(-1)(d+e)\right)\right] \right)\setminus (B\cap ( \lbrack k,k+1)%k+2)
    \cup C )\right\rbrack )\]
\end{document}

以下jakob.yaml是该方法的摘要:

  • 为每个$...$\[...\]处理主体,查找并存储除最外层出现的、 、 、 、\left(...\right]之外(...]\left[...\right)所有[...)内容\left(...\right)(...)

  • 最外层的出现\left(...\right)(...)替换为\left\lbrack...\right\rbrack

看看你的想法。毫无疑问,其他人可以做得更有效率。

jakob.yaml

replacements:
  -
    substitution: |-
      s/((?<!\\)\$|\\\[)    # opening between either $ or \[
            (.*?)           # body between $...$ or \[...\]
        ((?<!\\)\$|\\\])/   # closing $ or \]
        my $begin = $1;
        my $body = $2;
        my $end = $3;
        # operate on the body, only if it contains \mathbb
        if($body =~ m|\\mathbb|){
            my $storageToken = "jakob-paren-token";
            my $storageCount = 0;
            my @storageArray = ();
            # \left(...\right]
            # \left(...\right]
            # \left(...\right]
            my $leftRightRegEx = 
                qr|(
                    \\left\(         # \left(
                    (?:
                      (?!             
                       (?:\\left\()  # anything except \left(
                      ).
                    )*?
                    \\right\]        # up to \right]
                  )|xs;
            while( $body =~ m|$leftRightRegEx|xs ){
               $storageCount++;
               $body =~ s|$leftRightRegEx|
                    push(@storageArray,{id=>$storageToken.$storageCount,value=>$1});
                    $storageToken.$storageCount;|xse;
            }
            # (a,b]
            # (a,b]
            # (a,b]
            my $intervalRegEx = 
                qr|(
                    \(               # (
                    (?:
                      (?!
                        (?<!\\)\(    # anything except (
                      ).
                    )*?
                    (?<!\\)
                    \]               # up to ]
                  )|xs;
            while( $body =~ m|$intervalRegEx|xs ){
               $storageCount++;
               $body =~ s|$intervalRegEx|
                    push(@storageArray,{id=>$storageToken.$storageCount,value=>$1});
                    $storageToken.$storageCount;|xse;
            }
            # \left[...\right)
            # \left[...\right)
            # \left[...\right)
            $leftRightRegEx = 
                qr|(
                    \\left\[         # \left[
                    (?:
                      (?!             
                       (?:\\left\[)  # anything except \left[
                      ).
                    )*?
                    \\right\)        # up to \right)
                  )|xs;
            while( $body =~ m|$leftRightRegEx|xs ){
               $storageCount++;
               $body =~ s|$leftRightRegEx|
                    push(@storageArray,{id=>$storageToken.$storageCount,value=>$1});
                    $storageToken.$storageCount;|xse;
            }
            # [a,b)
            # [a,b)
            # [a,b)
            $intervalRegEx = 
                qr|(
                    \[               # [
                    (?:
                      (?!
                        (?<!\\)\[    # anything except [
                      ).
                    )*?
                    (?<!\\)
                    \)               # up to )
                  )|xs;
            while( $body =~ m|$intervalRegEx|xs ){
               $storageCount++;
               $body =~ s|$intervalRegEx|
                    push(@storageArray,{id=>$storageToken.$storageCount,value=>$1});
                    $storageToken.$storageCount;|xse;
            }
            # \left(...\right)
            # \left(...\right)
            # \left(...\right)
            my $untilNoNestedLeftRightRegEx = qr|\\left\(
                  (?:
                    (?!
                      (?<!\\right\))
                    ).
                  )*?
                  (?<!\\)
                  \\left\(|xs;
            $leftRightRegEx = 
                qr|(
                    \\left\(         # \left(
                    (?:
                      (?!             
                       (?:\\left\()  # anything except \left(
                      ).
                    )*?
                    \\right\)        # up to \right)
                  )|xs;
            while( $body =~ m|$untilNoNestedLeftRightRegEx|xs ){
               $storageCount++;
               $body =~ s|$leftRightRegEx|
                    push(@storageArray,{id=>$storageToken.$storageCount,value=>$1});
                    $storageToken.$storageCount;|xse;
            }
            # now store all matched (...)
            my $untilNoNestedParenRegEx = qr|\(
                  (?:
                    (?!
                      (?<!\\)\)
                    ).
                  )*?
                  (?<!\\)
                  \(|xs;
            my $parenRegEx = qr|(
                  \(
                  (?:
                    (?!
                      (?<!\\)\(
                    ).
                  )*?
                  (?<!\\)
                  \))|xs;
            while( $body =~ m|$untilNoNestedParenRegEx|){
               $storageCount++;
               $body =~ s|$parenRegEx|
                    push(@storageArray,{id=>$storageToken.$storageCount,value=>$1});
                    $storageToken.$storageCount;|xse;
            }
            # now make the substitution:
            #   \mathbb{(.*?)}\( (.*?) \)
            # into
            #   \mathbb{$1}\lbrack $2 \rbrack
            $body =~ s|(\\mathbb\{.*?\})\h*\((.*?)\)|$1\\left\\lbrack $2\\right\\rbrack|sg;
            $body =~ s|(\\mathbb\{.*?\})\h*\\left\((.*?)\\right\)|$1\\left\\lbrack $2\\right\\rbrack|sg;
            # finally, put the nested braces/intervals
            # back in to the body
            while(@storageArray){
                my $entry = pop(@storageArray);
                $body =~ s|${$entry}{id}|${$entry}{value}|s;
            }
        }
        $begin.$body.$end;/sgxe

相关内容