2

I am working on a simple text file in vim where I want to end every sentence with 2 spaces after full stop (dot/period). However, I do not want those sentences which already have 2 spaces after full stop to have further increase in spaces. The test text could be:

This sentence has only 1 space after it. This one has two.  This line has again 1 space only. This is last line. 

I tried:

%s/\. /\.  /g

but this increases all spaces by one. I tried following also but it does not work:

%s/\.  \\([^ ]\\)/.  \\1/g

How can I achieve this in vim?

rnso
  • 23,686
  • 25
  • 112
  • 234
  • Try `%s/\. \( \)\@!/. /g` (with 2 spaces in the replacement) – Wiktor Stribiżew Apr 26 '17 at 12:12
  • It does not work. Did u try it? – rnso Apr 26 '17 at 12:17
  • The `\( \)\@!` is a construct that fails a match if the pattern inside brackets appears in the string at the given location. – Wiktor Stribiżew Apr 26 '17 at 12:17
  • If it's at the end of each line you have to specify the end with $ like `%s/\. $/\. /g` – Hector Ventura Apr 26 '17 at 12:20
  • My text is in form of paragraphs with many sentences. In computer language each paragraph will be called a line. But I want to separate "sentences" by a dot and 2 spaces. Like all sentences in this comment are separated by dot and one space only. – rnso Apr 26 '17 at 12:22
  • OK. Your answer works - only that the replacement should be `/.__/` and not `/._/` (each _ indicates a space) as you have mentioned in your comment. Put this as an answer and I will accept it. The stackoverflow system is reducing 2 spaces to one. – rnso Apr 26 '17 at 12:24
  • 1
    That is why I wrote "(with 2 spaces in the replacement)". It is not the only problem with the SO comments, it also inserts rubbish into comment texts when using too long `code lines`. – Wiktor Stribiżew Apr 26 '17 at 12:28
  • Other answers have also appeared and `%s/\. \+/. /g` by @JimU is really easiest to understand. Thanks for your help. – rnso Apr 26 '17 at 12:43

5 Answers5

7

Replaces all periods followed by spaces with a period followed by 2 spaces

%s/\. \+/.  /g
Jim U
  • 3,318
  • 1
  • 14
  • 24
  • this is the simplest, thus most elegant solution. A win in vim-golf ☺ – zmo Apr 26 '17 at 12:28
  • 2
    However, the engine has to process each `.`+space (even those with just 2 spaces) with this approach. It will also shrink `.` + 3 or more spaces, and nothing is said about that in the question. When using a "lookaround", onyl relevant matches are actually replaced. – Wiktor Stribiżew Apr 26 '17 at 12:33
  • Yes, I think I do not want to reduce multiple spaces if I have intentionally put them there. – rnso Apr 26 '17 at 12:46
3

well, you shouldn't double the escapes, and it works:

:%s/\. \([^ ]\)/.  \1/g 

result:

This sentence has only 1 space after it.  This one has two.  This line has again 1 space only.  This is last line.~
zmo
  • 24,463
  • 4
  • 54
  • 90
  • It will be useful if you can explain here how it is working. – rnso Apr 26 '17 at 12:43
  • well, it's exactly the regex you wrote, except that your code was matching literally `. \(X\)` (because of the `\\`) instead of `. X` where `X` is anything but a space (and substitued as \1 in the RHS). – zmo Apr 26 '17 at 12:55
2

You may use

%s/\. \( \)\@!/.  /g

The \. \( \)\@! pattern matches a . and a space that is not followed with another space.

The (...)@! is a negative lookahead construct in Vim. See Lookbehind / Lookahead Regex in Vim. In other common regex flavors, it is written as (?!pattern). You may learn more about how negative lookaheads work in this answer of mine.

To match any whitespace, replace the literal space with \s inside the pattern.

Community
  • 1
  • 1
Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
  • What does @ do here? What is it for? – rnso Apr 26 '17 at 12:50
  • 1
    @mso: `(...)@!` is a negative lookahead construct in Vim. See [Lookbehind / Lookahead Regex in Vim](https://www.inputoutput.io/lookbehind-lookahead-regex-in-vim/). What in other, NFA, regex flavors is written as `(?!...)`. – Wiktor Stribiżew Apr 26 '17 at 12:55
1

Adds an extra space after periods followed by exactly one space

:%s/\. \zs\ze[^ ]/ /g
Jim U
  • 3,318
  • 1
  • 14
  • 24
0

Here is another possibility:

:%s/\.  \?/.  /g

The \? will capture a space (and only one) if it can, effectively not changing anything if there are already two spaces.

Alex867
  • 56
  • 6