Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
4
Help us understand the problem. What is going on with this article?
@sago35

Vim で表示しているテキストを外部プログラムで編集する

More than 1 year has passed since last update.

この記事は Vim Advent Calendar 2019 の 13 日目の記事です。

Vim は選択範囲であったり開いているテキスト全体であったりに対して、外部プログラムで編集することができます。
ここでは、 :{range}!{filter} [arg] を題材にして動きを確認していきます。

なお、詳細については :help complex-change もしくは :help filter に記載があります。

tate コマンドで縦書きに変換する

tate コマンドは、テキストを縦書きに変換するプログラムです。

$ type sample.txt | iconv -f utf-8 -t cp932
Vim で表示している

テキストを

外部プログラムで

編集する

↑ のような sample.txt に対して、 tate コマンドを使うと縦書きになります。

$ type sample.txt | tate
編 外 テ V
集 部 キ i
す プ ス m
る ロ ト  
  グ を で
  ラ   表
  ム   示
  で   し
      て
      い
      る

この動作を Vim 上で直接再現するのが filter コマンドになります。
ここでは、 :%!tate というコマンドで、テキスト全体を tate コマンドで処理してみます。

tate.gif

大体想定通りだと思いますが、 range で指定した範囲のテキストを filter で指定したプログラムの標準入力に渡し、プログラムの標準出力で出力されたテキストで置き換えることができます。

ちなみに、 tate コマンドは以下になります。

tate
https://github.com/mattn/tate

filter として使いやすいプログラム

sed / awk / Perl あたりのワンライナーで書きやすいプログラムが使いやすいです。
自分は、 Perl を良く使っていますので、いくつか例を示します。

サンプル 1 : すべて大文字化

A filter is a program that accepts text at standard input, changes it in some
way, and sends it to standard output.  You can use the commands below to send
some text through a filter, so that it is replaced by the filter output.
Examples of filters are "sort", which sorts lines alphabetically, and
"indent", which formats C program files (you need a version of indent that
works like a filter; not all versions do).  The 'shell' option specifies the
shell Vim uses to execute the filter command (See also the 'shelltype'
option).  You can repeat filter commands with ".".  Vim does not recognize a
comment (starting with '"') after the `:!` command.

:%!perl -anE "print uc($_)"

A FILTER IS A PROGRAM THAT ACCEPTS TEXT AT STANDARD INPUT, CHANGES IT IN SOME
WAY, AND SENDS IT TO STANDARD OUTPUT.  YOU CAN USE THE COMMANDS BELOW TO SEND
SOME TEXT THROUGH A FILTER, SO THAT IT IS REPLACED BY THE FILTER OUTPUT.
EXAMPLES OF FILTERS ARE "SORT", WHICH SORTS LINES ALPHABETICALLY, AND
"INDENT", WHICH FORMATS C PROGRAM FILES (YOU NEED A VERSION OF INDENT THAT
WORKS LIKE A FILTER; NOT ALL VERSIONS DO).  THE 'SHELL' OPTION SPECIFIES THE
SHELL VIM USES TO EXECUTE THE FILTER COMMAND (SEE ALSO THE 'SHELLTYPE'
OPTION).  YOU CAN REPEAT FILTER COMMANDS WITH ".".  VIM DOES NOT RECOGNIZE A
COMMENT (STARTING WITH '"') AFTER THE `:!` COMMAND.

サンプル 2 : SREC の S0 レコードをデコード

443A5C446174615C5358313231325F4150495C4150495C4150495F636F64655C が ASCII の 16 進数表記になっているので変換するという例。
Vim のコマンドラインモードでは、 % がファイル名に変換されてしまうので \% と書く必要があることに注意。

S02B0000443A5C446174615C5358313231325F4150495C4150495C4150495F636F64655C7475746F7269616C44

:%!perl -ape "s/^(S0......)((..)+)(..$)/sprintf qq'\%s\%s\%s', $1, pack('H*', $2), $3/e"

S02B0000D:\Data\SX1212_API\API\API_code\tutorial6C

サンプル 3 : 前の行のタイムスタンプとの差分を追加しつつ、 ID (3 カラム目) 毎の差分も出す

4.303006 1  1               Rx   d 8 00 00 00 00 00 00 00 00
4.413445 1  1               Rx   d 8 00 00 00 00 00 00 00 00
4.480696 1  2               Rx   d 8 00 57 00 00 00 00 00 00
4.482131 1  4               Rx   d 8 00 57 00 00 00 00 00 00
4.523533 1  1               Rx   d 8 00 00 00 00 00 00 00 00
4.634201 1  1               Rx   d 8 00 00 00 00 00 00 00 00
4.743692 1  1               Rx   d 8 00 00 00 00 00 00 00 00
4.780966 1  2               Rx   d 8 00 57 00 00 00 00 00 00
4.782392 1  4               Rx   d 8 00 57 00 00 00 00 00 00
4.853831 1  1               Rx   d 8 00 00 00 00 00 00 00 00
4.963971 1  1               Rx   d 8 00 00 00 00 00 00 00 00

:%!perl -ape "s/^/sprintf '\%.6f \%.6f ', $F[0]-$x{$F[2]}, $F[0]-$y/e; $x{$F[2]}=$F[0]; $y=$F[0]"

// 左から `ID 毎差分`、 `差分`、 `元のテキスト` を表示
4.303006   4.303006   4.303006 1  1               Rx   d 8 00 00 00 00 00 00 00 00
0.110439   0.110439   4.413445 1  1               Rx   d 8 00 00 00 00 00 00 00 00
4.480696   0.067251   4.480696 1  2               Rx   d 8 00 57 00 00 00 00 00 00
4.482131   0.001435   4.482131 1  4               Rx   d 8 00 57 00 00 00 00 00 00
0.110088   0.041402   4.523533 1  1               Rx   d 8 00 00 00 00 00 00 00 00
0.110668   0.110668   4.634201 1  1               Rx   d 8 00 00 00 00 00 00 00 00
0.109491   0.109491   4.743692 1  1               Rx   d 8 00 00 00 00 00 00 00 00
0.300270   0.037274   4.780966 1  2               Rx   d 8 00 57 00 00 00 00 00 00
0.300261   0.001426   4.782392 1  4               Rx   d 8 00 57 00 00 00 00 00 00
0.110139   0.071439   4.853831 1  1               Rx   d 8 00 00 00 00 00 00 00 00
0.110140   0.110140   4.963971 1  1               Rx   d 8 00 00 00 00 00 00 00 00

まとめ

以上のように、外部プログラムを使って簡単なテキスト編集ができました。
今回紹介したサンプルは Perl 中心ですが、他のプログラムでも同様の事が可能です。
使い慣れたプログラムでフィルタ処理をして、テキスト編集を快適にしていきましょう。

4
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
sago35
現職は、車載組込エンジニア。 仕事では主にC言語、ツール類はperlおよびgolangで作成。

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
4
Help us understand the problem. What is going on with this article?