sedで少しずつプログラムを編集する訓練をしてみます。C言語で、偽echoコマンドを作ります。
最初だけは、sedを使う意味がないので、catにしておきます。
takk@takk:~$ cat <<.>myecho.c > #include <stdio.h> > int main(int argc, char* argv[]) > { > printf("%s\n",argv[1]); > } > . takk@takk:~$
できました。ファイル名はmyecho.cとしました。引数[1]が指定されていること前提のコマンドですが、少しずつsedで置換していきましょう。
次はコンパイルします。実行ファイルはmyechoとします。
takk@takk:~$ gcc -o myecho myecho.c
何も表示されないということは、上手くビルドできたということです。確認しましょう。
takk@takk:~$ ls -l 合計 12 -rwxr-xr-x 1 takk takk 4916 9月 14 21:21 myecho -rw-r--r-- 1 takk takk 82 9月 14 21:21 myecho.c
使ってみます。
takk@takk:~$ ./myecho HELLO HELLO takk@takk:~$
いい感じです。
しかし、先ほども描きましたが、引数がないとエラーとなります。
takk@takk:~$ ./myecho Segmentation fault takk@takk:~$
argcを見て、プログラム本体を含め引数が2つ以上あれば、printfを実行するようにif文を追加します。
takk@takk:~$ sed '/{/a if(--argc)' myecho.c #include <stdio.h> int main(int argc, char* argv[]) { if(--argc) printf("%s\n",argv[1]); } takk@takk:~$
-iオプションで置換確定します。
takk@takk:~$ !! -i sed '/{/a if(--argc)' myecho.c -i takk@takk:~$
置換されたかcatで確認しましょう。
takk@takk:~$ cat myecho.c #include <stdio.h> int main(int argc, char* argv[]) { if(--argc) printf("%s\n",argv[1]); } takk@takk:~$
ビルドして、引数なしの時、ありの時を確認します。
takk@takk:~$ !gc gcc -o myecho myecho.c takk@takk:~$ ./myecho takk@takk:~$ ./myecho HELLO HELLO takk@takk:~$
OKです。
echoコマンドは、以下のように空白で区切って連続で文字列を表示することができます。
takk@takk:~$ echo HELLO GOODBYE HELLO GOODBYE takk@takk:~$
myechoはどうでしょうか。
takk@takk:~$ ./myecho HELLO GOODBYE HELLO takk@takk:~$
当然ですが、一個しか表示されません。では、if文をwhileに変えてみます。
takk@takk:~$ sed 's/if/while/' myecho.c #include <stdio.h> int main(int argc, char* argv[]) { while(--argc) printf("%s\n",argv[1]); } takk@takk:~$ !! -i sed 's/if/while/' myecho.c -i takk@takk:~$
次に、argv[1]決め打ちではなく、複数の引数に対応できるようにポインタを使います。
takk@takk:~$ sed '/pr/s/argv.../*++argv/' myecho.c #include <stdio.h> int main(int argc, char* argv[]) { while(--argc) printf("%s\n",*++argv); } takk@takk:~$ !! -i sed '/pr/s/argv.../*++argv/' myecho.c -i takk@takk:~$
コンパイル。
takk@takk:~$ !gc gcc -o myecho myecho.c takk@takk:~$
引数の複数指定を試してみましょう。
takk@takk:~$ ./myecho HELLO GOODBYE HELLO GOODBYE takk@takk:~$
空白で区切るところを、改行されてしまいました。修正します。
takk@takk:~$ sed 's/\\n/%s/;/pri/s/)/ ,argc==1 ?"\\n":" ")/' myecho.c #include <stdio.h> int main(int argc, char* argv[]) { while(--argc) printf("%s%s",*++argv ,argc==1 ?"\n":" "); } takk@takk:~$ !! -i sed 's/\\n/%s/;/pri/s/)/ ,argc==1 ?"\\n":" ")/' myecho.c -i takk@takk:~$
一行に書くため三項演算子を使いました。 さて上手く実行できるでしょうか。
takk@takk:~$ !gc gcc -o myecho myecho.c takk@takk:~$ ./myecho HELLO GOODBYE HELLO GOODBYE takk@takk:~$
引数を増やしても、上手くいきますね。
takk@takk:~$ ./myecho {1..10} 1 2 3 4 5 6 7 8 9 10 takk@takk:~$
最後にソースを整形します。
takk@takk:~$ indent myecho.c
出来上がったmyechoのソースです。
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:~$
コメント
[…] ← sedを使ってechoコマンドを少しずつ作る […]