Matching nested braces/brackets is not trivial; I propose the following which is a regular expression that plugs into perl via latexindent and its yaml interface. There's nothing to stop you from incorporating this into your own perl script.
The command that I used to generate the output is
latexindent -rr -l=jakob.yaml myfile.tex -o=output.tex
output.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}
and here's jakob.yaml; a summary of the approach is:
for each $...$ and \[...\] process the body by finding and storing all but the outer-most occurrences of \left(...\right], (...], \left[...\right), [...), \left(...\right), (...)
for the outer-most occurrences of \left(...\right) and (...) replace them with \left\lbrack...\right\rbrack
See what you think. Doubtless others could do this more efficiently.
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
(and then use a command likechange surronding delimiteror the equivalent for your mode, checking the changes one by one. – Rmano Feb 14 '20 at 09:02