6

I want find all \textbf in my .tex file and delete it, together with it's argument braces {}. For example, I want to change:

  1. \textbf{text} to text

  2. \textbf{text \textit{textbis}} to text \textit{textbis}

  3. \textbf{\textit{\textls[-5]{textbis}} text} to \textit{\textls[-5]{textbis}} text

  4. \textbf{\textit{X{textbis}} text} to \textit{X{textbis}} text (where X is a paragraph break).

I tried to use \\textbf\{([^}]*)\} in \1 but it didn't work because it stops at first }.

Werner
  • 603,163
user48106
  • 171
  • 4
    You can not match braces to arbitrary depth with a (real) regular expression, that's essentially what "regular" means. – David Carlisle Mar 24 '14 at 20:09
  • 3
    It is easiest to add \let\textbf\relax to your document preamble if you want to remove the functionality of \textbf altogether. You can then leave \textbf in your document and it will have no effect. – Werner Mar 24 '14 at 20:14
  • This is a fine topic for nested lists handling. Back to TeX, I use \def\textbf#1{#1}. – Malipivo Mar 24 '14 at 20:24
  • 3
    @Werner \let\texbf\@firstofone – egreg Mar 24 '14 at 20:46
  • 4
    This shows that one should always use semantic markup. That is, instead of using \textbf{...} define a macro say \important. That way, if at a later stage you want to change how the output looks, you can just redefine the macro \important. – Aditya Mar 24 '14 at 21:12
  • @Aditya: Yes, as suggested in Consistent typography... – Werner Mar 24 '14 at 21:17
  • I bet you there is an elegant solution in Sublime Text. Is there way to enter a variable in the "Find" field for the "Search and Replace" feature of Sublime (or any other editor)? – Far Zin Mar 25 '14 at 08:49
  • i dont want put nothing in the preamble (only necessary to stat tex ^^).

    Then there's a system to clear my file quicly with a regular expression that understand when finish a determinate gruop? Or i need delete all \textbf and after find all { } not necessary manually?

    THX all again

    Vitaliano

    – user48106 Mar 25 '14 at 10:22
  • Why not (and someone cleverer than me will say why not) define a macro: \newcommand{\notbold}[1]{#1} and change all your \textbf{s to s\notbold{s (you don't even need regex)? This then doesn't wipe out\textbf` in case you need it again. – Chris H Mar 25 '14 at 11:32

2 Answers2

3

As already mentioned by @David Carlisle you cannot match an arbitrary number of well-nested { } pairs. But, from a practical perspective, you may know an upper-bound on the maximum nesting level. If this bound is known, then it is possible to write a regular expression recognizing well-parenthesised expressions up to the maximum nesting level.

To recognise \texbf{normal text} (max nest = 1) you can do

\textbf{([^{}]*)}

forbidding { inside the brackets is a precaution to never match things with nesting level greater than your maximum.

To match things with max nest = 2 you can do the following:

  1. first you match \\textbf\{
  2. then you match any non bracket character with [^{}]*
  3. now you may have finished matching the contents (the actual nesting level is 1) and happily match the ending \}
  4. or, you could be in a position with an open bracket. In this case you need to match something with nesting level 0, and then match the closed bracket.

Steps 2, 3 and 4 correspond to [^{}]*(\{[^{}]*\}[^{}]*)? which may be repeated so you can match things like \textbf{bla\bla{bla}bla\bla{bla}bla}

So all in all the max nest level = 2 regex looks like this

\\textbf\{(([^{}]*(\{[^{}]*\}[^{}]*)?)*)\}

We can extrapolate the scheme for max nest = N greater than 2:

\\textbf\{(([^{}]*(\{RN\}[^{}]*)?)*)\}

where

R1 = [^{}]*
RN = ([^{}]*(\{R(N-1)\}[^{}]*)?)*

So for example with max nest = 3 you get

\\textbf\{(([^{}]*(\{(([^{}]*(\{[^{}]*\}[^{}]*)?)*)\}[^{}]*)?)*)\}

which is sufficient to catch all the cases you mention in the question.

Bordaigorl
  • 15,135
1

if you can use non-greedy quantifiers,

replace \\textbf\{(.*?)\} with \1

Ok, as Werner mentioned, this only works with non-nested commands. I think, there is no simple solution for this and it's a parser job.

If you want to do it anyway with Regex, you could replace the non-\textbf-brackets with a non-used symbol, and at then end remove the \textbf-brackets and change the symbols back to brackets:

1) Replace all closing non-\textbf-brackets } with Symbol A,

2) Replace all opening non-\textbf-brackets { with Symbol B,

3) Replace the remaining \textbf{ and } (from \textbf) with nothing,

4) Replace Symbol A with { and Symbol B with }


@Step 1 and 2:

Step 1: } -> Smybol A, in my example german ö:

(?<=(?<!\\textbf)\{(?!.*?\{)).*?\}

Replace this expression with \1ö (I didn't found a better solution for this expression)


Then do Step 2: { -> Symbol B, in my example german ä

(?<!\\textbf)\{(?!.*?\{)

Replace this expression with ä.


Redo these steps as many nested levels you have. Then follow the remaining steps.


Well, this is more a regex-macro and a workaround than a solid regex, but it should work.
musicman
  • 3,559
  • Doesn't "greedy" refer to the same problem the OP experienced? That is, the first } is considered the closing group for \textbf, which is not always the case? – Werner Mar 24 '14 at 21:18
  • Step 1 say me invalid pattern in look-behind – user48106 Mar 25 '14 at 10:14
  • It's working with Notepad++ – musicman Mar 25 '14 at 10:49
  • i'm trid your code in first step in this text : "in alcuni casi, patologia. \textbf{\textit{L’immagine} corporea} è un’immagine dinamica che dipende da fattori non solo biologici, relativi ai cambiamenti fisiologici del corpo, ma anche psicologici e sociali. Il corpo, infatti, è il crocevia delle interazioni sociali, dei riconoscimenti e delle accettazioni, è la “visualizzazione” del progetto identitario di ciascuno.}

    \end{document}"

    he find L’immagine} and document}

    – user48106 Mar 25 '14 at 11:22
  • I've edited my post again (numbering). Look again at step 1: Yes, it will find L'immagine}, but in 2 groups: L'immagine is \1 and } is \2. That's why you replace the pattern with \1ä. – musicman Mar 25 '14 at 11:34