3

I'm attempting to replace all strings in a text file surrounded by single quotes and ending with an @ first followed by any number and then any mix of any other letter(s) or #(s) like these:

'package@1.1.k'
'otherpackage@14'
'anotherpackage@7.8'

and I wish to select only the single quotes and remove them like so:

export MYVAR="/dir/'package@1.1.k':$MYVAR" 

to:

export MYVAR="/dir/package@1.1.k:$MYVAR"

in the entire file. I figured out a way to remove the proceeding single quote and preceding single quote in two separate commands (using vim's zs and ze, similar to positive and negative lookarounds):

:%s/'.*@.[0-9]*.*\zs'//g 
:%s/\zs'\ze.*@.[0-9]*.*//g

However, I am curious about doing it in a single operation as I want to learn more about using Neovim, and apply the answer to future operations.

I am actually using Neovim, if that comes with any additional features related to this.

romainl
  • 186,200
  • 21
  • 280
  • 313
eyeseaevan
  • 121
  • 7
  • @CarySwoveland I'm sorry that was a typo. I meant followed by. Thank you, I fixed my question. However, I know the regex for that match, my primary question is about selecting two characters (or possibly in another case – strings), that are separated by other characters and/or whitespace without selecting what's in between. – eyeseaevan May 11 '22 at 01:34

2 Answers2

4

You need to use

%s/'\([^@'0-9]*@[0-9][^']*\)'/\1/g

Details:

  • ' - a single quote
  • \( - start of a capturing group
    • [^@'0-9]* - zero or more chars other than @, ' and digits
    • @ - a @ char
    • [0-9] - a digit
    • [^']* - zero or more chars other than a ' char
  • \)' - end of the capturing group.

The replacement is \1, the Group 1 backreference/placeholder.

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
  • *Tysm!!:) For anyone confused about* **how to insert into / replace both of the selections instead of removing them –** replace the outer `'` `'` in the %s/ command with the characters you wish to replace. Put what you wish to replace the first selection with in the replacement field after the `/` before the `\1` backreference, and what to replace the second selection with after, like so ........ : `:%s/'\([^@'0-9]*@[0-9][^']*\)'/PREPEND\1APPEND` – eyeseaevan May 12 '22 at 13:26
3

You can replace matches of the following regular expression with the content of capture group 1.

'([^@']*@\d[^@']*)'

Demo

I'm not familiar with Vim's regex engine, but I understand it is quite robust. Considering that the regular expression I have suggested is nothing fancy (just making use of a capture group) I'm confident it should work in Vim.

The regular expression can be broken down as follows.

'           # match a single quote
(           # begin capture group 1
  [^@']*    # match zero or more characters other than '@' and a single-quote
  @\d       # match '@' followed by a digit ofollowed by zero or more characters
            # other than '@' and a single-quote
  [^@']*    # match zero or more characters other than '@' and a single-quote
)           # end capture group 1
'           # match a single quote

I've assumed that there can be at most one '@' between asterisks, but if more that one is permitted (if, for example, 'a@11@22*' is to be converted to a@11@22*) change the regular expression to

'([^']*@\d[^']*)'
Cary Swoveland
  • 106,649
  • 6
  • 63
  • 100