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.

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.

  • 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 3: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 8:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.