0

I want to find and remove the exclamation mark in the second and third lines only but retain the exclamations marks in the first line.

[some text !]
[some text !
some text !

I've tried :

(?<!\[.*)(!)(?!.*\])

However, look behinds cannot consume any characters.

bobble bubble
  • 16,888
  • 3
  • 27
  • 46
akhiler
  • 13
  • 2
  • 1
    What tool/flavor do you use? – InSync May 02 '23 at 04:29
  • autohotkey or in notepad++ – akhiler May 02 '23 at 04:31
  • What about: `[some ! text]` — `(some text !)` — `(some text !` — `some! text` — `!not this one?`, etc. Also, what should the output be — is it OK to leave spaces that appeared before or after the exclamation mark? (It is a lot easier if there's no need to pay attention to spacing!) In other words, you need to be much more precise about when the exclamation mark should be kept and when it should be removed. – Jonathan Leffler May 02 '23 at 05:08

1 Answers1

1

In Notepad++, replace:

(                # Capturing group consisting of
  ^\[            # a square bracket at the beginning of line,
  [^[\]]*        # 0+ non-bracket characters, then
  \]$            # a closing bracket at the end of line,
)                # 
|                # or
!                # a literal '!'

with:

\1

This matches all square-bracketed strings and exclamation marks, but since we're capturing the former and add that back, only the exclamation marks will be removed.

Try it on regex101.com.

If the brackets are not guaranteed to be at the beginning/end of line, simply remove ^ and $: (\[[^[\]]*\])|!. Note that this may match square-bracketed multi-line strings:

[some tex!t !]
[som!e text !
!some text !
] ! foobar

...becomes:

[some tex!t !]
[som!e text !
!some text !
]  foobar

Try it on regex101.com.

To limit the match on one line, add a \n to the character class: (\[[^[\]\n]*\])|!.

Try it on regex101.com.

Alternatively, use (*SKIP)(*FAIL) to forgo the first part, as suggested by bobble bubble: \[[^[\]\n]\](*SKIP)(*FAIL)|!.

Try it on regex101.com.

InSync
  • 4,851
  • 4
  • 8
  • 30
  • 1
    thanks, this was it! More simply for my purposes: (\[.*\])|! the key was to capture any characters within the brackets and then find the exclamation mark. – akhiler May 02 '23 at 05:16
  • `(\[.*\])` [might not](https://regex101.com/r/h18O8k/4) match [as expected](https://regex101.com/r/h18O8k/5). – InSync May 02 '23 at 05:19
  • Nice answer! Worth to mention, in PCRE even [verbs `(*SKIP)(*F)`](https://stackoverflow.com/questions/24534782/how-do-skip-or-f-work-on-regex) [could be used (demo)](https://regex101.com/r/ACu6MM/1). – bobble bubble May 02 '23 at 11:20
  • 1
    That's something new to me. Thanks, updated. – InSync May 02 '23 at 14:26