(Linux)edラインエディタでechoコマンドのソースにgetoptを追加

1-3.コマンドライン操作

sedを使ってechoコマンドを少しずつ作る」で作ったニセechoコマンドmyechoに、オプション処理を追加します。追加するオプションは、-n、改行しないオプションです。

では現在のソースを確認します。

takk@takk:~$ cat -n myecho.c
     1	#include <stdio.h>
     2	int
     3	main (int argc, char *argv[])
     4	{
     5	  while (--argc)
     6	    printf ("%s%s", *++argv, argc == 1 ? "\n" : " ");
     7	}
takk@takk:~$ 

edを開きます。

takk@takk:~$ ed myecho.c
128

全体を表示します。さきほどのcatと同じですね。

,n
1	#include <stdio.h>
2	int
3	main (int argc, char *argv[])
4	{
5	  while (--argc)
6	    printf ("%s%s", *++argv, argc == 1 ? "\n" : " ");
7	}

include行(1行目)をコピーします。

1t1

コピーされたか1〜3行目を表示してみましょう。

1,3n
1	#include <stdio.h>
2	#include <stdio.h>
3	int

新たにunistd.hをincludeしたいので、2行目のstdioをunistdに置換します。

2s/stdio/unistd
#include <unistd.h>

置換されました。

次にgetoptの戻り値を格納する変数を追加します。
ついでにnオプションのフラグ変数も追加します。

3回Enterを押して、mainの後の{を見つけましょう。


int

main (int argc, char *argv[])

{

ここに行を追加するため、aコマンドを使います。a、Enterと入力します。

a

変数定義を追加したら、.(ピリオド)、Enterで、入力モードを抜けます。

int nflag;
.

複写しましょう。

t.

nflagをoptに置換します。

s/nflag/opt
int opt;

ソース全体を見てみましょう。

,n
1	#include <stdio.h>
2	#include <unistd.h>
3	int
4	main (int argc, char *argv[])
5	{
6	int nflag;
7	int opt;
8	  while (--argc)
9	    printf ("%s%s", *++argv, argc == 1 ? "\n" : " ");
10	}

次は7行目の後からgetopt処理を追加していきます。後でソース整形するので、インデントは気にせず入力します。

7a
while((opt=getopt(argc,argv,"n")) != -1){
switch(opt){
case 'n':
nflag=1;
break;
}
}
.

nflagの初期値を0にしておきます。

6s/;/=0;

全体を見てみましょう。

,n
1	#include <stdio.h>
2	#include <unistd.h>
3	int
4	main (int argc, char *argv[])
5	{
6	int nflag=0;
7	int opt;
8	while((opt=getopt(argc,argv,"n")) != -1){
9	switch(opt){
10	case 'n':
11	nflag=1;
12	break;
13	}
14	}
15	  while (--argc)
16	    printf ("%s%s", *++argv, argc == 1 ? "\n" : " ");
17	}

オプション処理した分だけ、argcとargvを進めます。
14行目の後からこの処理を追加します。

14a
argc-=optind;
argv+=optind;
.

Enterを、1回押して、次のwhile分を表示します。

  while (--argc)

argcとargvを進めたので、コマンド名とオプションを含まない引数の最初からargv[0]に格納されています。argcも引数の数になっていますので、–argcをargc–、++argvもargv++に置換します。

s/--argc/argc--
  while (argc--)

Enterを、1回押して、次のprintfへ。

    printf ("%s%s", *++argv, argc == 1 ? "\n" : " ");

s/++argv/argv++
    printf ("%s%s", *argv++, argc == 1 ? "\n" : " ");

s/1/0
    printf ("%s%s", *argv++, argc == 0 ? "\n" : " ");

一旦保存してedを終了しましょう。

wq
283
takk@takk:~$ 

ビルドは通るでしょうか。

takk@takk:~$ gcc -o myecho myecho.c
takk@takk:~$ 

通りました。確認します。

takk@takk:~$ ./myecho {1..10}
1 2 3 4 5 6 7 8 9 10
takk@takk:~$ ./myecho
takk@takk:~$ ./myecho {1..10} -n
1 2 3 4 5 6 7 8 9 10
takk@takk:~$ 

おっと、肝心な-nオプションの処理を忘れてしました。
再度edでmyecho.cを開きます。

takk@takk:~$ ed myecho.c
283

printfの行を表示します。pr,Enterと入力。

/pr
    printf ("%s%s", *argv++, argc == 0 ? "\n" : " ");

nオプションが指定されたら改行しないようにする修正です。

s/argc/(nflag == 0 \&\& argc
    printf ("%s%s", *argv++, (nflag == 0 && argc == 0 ? "\n" : " ");
s/0 ?/0) ?
    printf ("%s%s", *argv++, (nflag == 0 && argc == 0) ? "\n" : " ");
wq
299

ビルドして確認しましょう。

takk@takk:~$ !gc
gcc -o myecho myecho.c
takk@takk:~$ ./myecho {1.10}
{1.10}
takk@takk:~$ !! -n
./myecho {1.10} -n
{1.10} takk@takk:~$ 

うまく-nオプションが効きました。

コメント

タイトルとURLをコピーしました