5

I need to transform the full-width characters(NBA) in the following sentence to half-width ones.

NBA中曾有“怒吼天尊”之称的已退役球员是谁? 拉希德·华莱士
H5N2疫苗可对抗H5禽流感病毒

I know I can realize it in Python using unicodedata.normalize module(with a parameter "NFKC"). But is there any method to do it directly in Vim? I have tried char2nr and eval and found that they don't work.

Lerner Zhang
  • 740
  • 7
  • 19

1 Answers1

6

There you go:

:%s/[\uff01-\uff5e]/\=nr2char(char2nr(submatch(0))-65248)/g

This matches the range of full-width characters, and via :help sub-replace-expr and char2nr() converts this to a number, subtracts to get this into the ASCII range for ! - ~, and converts it back to characters.

Addendum

If you need to support other (non-contiguous) characters, you can define a Map and check that first. For example, for the arrow symbols mentioned in your comment:

let g:fullToHalf = { "\u2190": "\uFFE9", "\u2192": "\uFFEB", "\u2191": "\uFFEA", "\u2193": "\uFFEC" }
:execute '%s/[\uff01-\uff5e' . join(keys(g:fullToHalf), ''). ']/\=get(g:fullToHalf, submatch(0), nr2char(char2nr(submatch(0))-65248))/g'

Note: As a one-liner, this gets really ugly. I would strongly recommend to put this into a function.

Ingo Karkat
  • 17,819
  • 1
  • 45
  • 61
  • Thanks very much again for your awesome answer. But any ideas for the half-width characters outside of the ASCII range? I mean especially for those with full-width characters of Unicode [\uff5f-\uff65\uffda-\uffee]? For example in this table. – Lerner Zhang Dec 10 '16 at 03:08
  • 1
    It can be done; I've extended my answer. – Ingo Karkat Dec 11 '16 at 20:43
  • Any chance you can define a bash script version of this combined range and map approach to replace all full width characters with half width equivalents found in a file? I need to accomplish this in a stand alone bash script (not within vi or vim). – Streamline Dec 17 '17 at 21:56
  • @Streamline You can invoke Vim non-interactively from a shell script. Usually it's better to use specialized tools like sed or awk, but this may be a valid case for Vim. For details, see e.g. here. – Ingo Karkat Dec 19 '17 at 08:28