GNU/Linux >> Linux の 問題 >  >> Linux

コマンドライン引数を解析する C argc および argv の例

端末でプログラムを実行するときはいつでも、プログラムが期待するいくつかの引数を渡すことができます。これらの引数は、プログラムの実行中に使用できます。ここで、システムは、プログラムの実行中にユーザーから渡されたすべての引数を維持するための内部機能を提供します。これらの引数は「コマンド ライン引数」として知られています。

このチュートリアルでは、コマンド ライン引数の理解を実際のプログラムにマッピングして、より明確に理解できるようにします。ただし、プログラムにジャンプする前に、システムがコマンドライン引数の機能をどのように提供するかを知っておく必要があります。ご存知のように、すべての C プログラムには main() 関数が必要であり、コマンド ライン引数の機能は main() 関数自体によって提供されます。以下の宣言がプログラムで使用されている場合、プログラムにはコマンドライン引数を使用/操作する機能があります。

int main (int argc, char *argv[])

ここで、argc パラメーターは、実行時に実行可能ファイルに渡されるコマンド ライン引数の総数です (最初の引数として実行可能ファイルの名前を含む)。 argv パラメータは、実行時に実行可能ファイルに渡される各コマンド ライン引数の文字列の配列です。 C プログラミングが初めての場合は、まず C 配列がどのように機能するかを理解する必要があります。

以下は、コマンドライン引数を使用した作業プログラムです。

 #include <stdio.h>

 int main (int argc, char *argv[]) {
 int i=0;
 printf("\ncmdline args count=%s", argc);

 /* First argument is executable name only */
 printf("\nexe name=%s", argv[0]);

 for (i=1; i< argc; i++) {
     printf("\narg%d=%s", i, argv[i]);
 }

 printf("\n");
 return 0;
 }

以下は、プログラム実行時の出力です。

$ ./cmdline_basic test1 test2 test3 test4 1234 56789
cmdline args count=7
 exe name=./cmdline_basic
 arg1=test1
 arg2=test2
 arg3=test3
 arg4=test4
 arg5=1234
 arg6=56789

上記の出力では、引数の合計数が値「7」を保持する main() の「argc」パラメーターによって内部的に維持されていることがわかります (1 つの引数は実行可能ファイル名で、「6」はプログラムに渡される引数です)。引数の値は、文字列の配列である main() の「argv」パラメータに格納されます。ここで、main() 関数は各引数の値を文字列として格納します。 「argv」配列を反復処理すると、プログラムで渡されたすべての引数を取得できることがわかります。

プログラム内の環境変数を処理する追加機能を提供する main () 関数の宣言がもう 1 つあります。同様に、argv[] 配列で維持される引数と同様に、main() 関数には、すべてのシステム環境変数を main() 関数パラメーターとして使用できる文字列の配列に維持する内部機能があります。以下に宣言を示します。

int main (int argc, char *argv[], char **envp)

以下に、コマンドライン引数と環境変数を使用した作業プログラムを示します。

#include <stdio.h>

int main (int argc, char *argv[], char **env_var_ptr) {
int i=0;
printf("\ncmdline args count=%d", argc);

/* First argument is executable name only */
printf("\nexe name=%s", argv[0]);

for (i=1; i< argc; i++) {
   printf("\narg%d=%s", i, argv[i]);
 }

i=0;
while (*env_var_ptr != NULL) {
    i++;
    printf ("\nenv var%d=>%s",i, *(env_var_ptr++));
 }

printf("\n");
return 0;
}

上記のプログラムの出力を以下に示します。

$ ./env test1 test2
cmdline args count=3
 exe name=./env
 arg1=test1
 arg2=test2
 env var1=>SSH_AGENT_PID=1575
 env var2=>KDE_MULTIHEAD=false
 env var3=>SHELL=/bin/bash
 env var4=>TERM=xterm
 env var5=>XDG_SESSION_COOKIE=5edf27907e97deafc70d310550995c84-1352614770.691861-1384749481
 env var6=>GTK2_RC_FILES=/etc/gtk-2.0/gtkrc:/home/sitaram/.gtkrc-2.0:/home/sitaram/.kde/share/config/gtkrc-2.0
 env var7=>KONSOLE_DBUS_SERVICE=:1.76
 env var8=>KONSOLE_PROFILE_NAME=Shell
 env var9=>GS_LIB=/home/sitaram/.fonts
 env var10=>GTK_RC_FILES=/etc/gtk/gtkrc:/home/sitaram/.gtkrc:/home/sitaram/.kde/share/config/gtkrc
 env var11=>WINDOWID=29360154
 env var12=>GNOME_KEYRING_CONTROL=/run/user/sitaram/keyring-2Qx7DW
 env var13=>SHELL_SESSION_ID=f7ac2d9459c74000b6fd9b2df1d48da4
 env var14=>GTK_MODULES=overlay-scrollbar
 env var15=>KDE_FULL_SESSION=true
 env var16=>http_proxy=http://10.0.0.17:8080/
 env var17=>USER=sitaram
 env var18=>LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lz=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.axa=00;36:*.oga=00;36:*.spx=00;36:*.xspf=00;36:
 env var19=>XDG_SESSION_PATH=/org/freedesktop/DisplayManager/Session0
 env var20=>XDG_SEAT_PATH=/org/freedesktop/DisplayManager/Seat0
 env var21=>SSH_AUTH_SOCK=/tmp/ssh-kIFY5HttOJxe/agent.1489
 env var22=>ftp_proxy=ftp://10.0.0.17:8080/
 env var23=>SESSION_MANAGER=local/Sitaram:@/tmp/.ICE-unix/1716,unix/Sitaram:/tmp/.ICE-unix/1716
 env var24=>DEFAULTS_PATH=/usr/share/gconf/kde-plasma.default.path
 env var25=>XDG_CONFIG_DIRS=/etc/xdg/xdg-kde-plasma:/etc/xdg
 env var26=>DESKTOP_SESSION=kde-plasma
 env var27=>PATH=/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
 env var28=>PWD=/home/sitaram/test_progs/cmdline
 env var29=>socks_proxy=socks://10.0.0.17:8080/
 env var30=>KONSOLE_DBUS_WINDOW=/Windows/1
 env var31=>KDE_SESSION_UID=1000
 env var32=>LANG=en_IN
 env var33=>GNOME_KEYRING_PID=1478
 env var34=>MANDATORY_PATH=/usr/share/gconf/kde-plasma.mandatory.path
 env var35=>UBUNTU_MENUPROXY=libappmenu.so
 env var36=>KONSOLE_DBUS_SESSION=/Sessions/1
 env var37=>https_proxy=https://10.0.0.17:8080/
 env var38=>GDMSESSION=kde-plasma
 env var39=>SHLVL=1
 env var40=>HOME=/home/sitaram
 env var41=>COLORFGBG=15;0
 env var42=>KDE_SESSION_VERSION=4
 env var43=>LANGUAGE=en_IN:en
 env var44=>XCURSOR_THEME=Oxygen_White
 env var45=>LOGNAME=sitaram
 env var46=>XDG_DATA_DIRS=/usr/share/kde-plasma:/usr/local/share/:/usr/share/
 env var47=>DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-mnJhMvd4jG,guid=435ddd41500fd6c5550ed8d2509f4374
 env var48=>LESSOPEN=| /usr/bin/lesspipe %s
 env var49=>PROFILEHOME=
 env var50=>XDG_RUNTIME_DIR=/run/user/sitaram
 env var51=>DISPLAY=:0
 env var52=>QT_PLUGIN_PATH=/home/sitaram/.kde/lib/kde4/plugins/:/usr/lib/kde4/plugins/
 env var53=>LESSCLOSE=/usr/bin/lesspipe %s %s
 env var54=>XAUTHORITY=/tmp/kde-sitaram/xauth-1000-_0
 env var55=>_=./env
 env var56=>OLDPWD=/home/sitaram/test_progs
$

上記の出力では、すべてのシステム環境変数を main() 関数の 3 番目のパラメーターとして取得できることがわかります。これらはプログラム内で走査され、出力に表示されます。

引数をプログラムおよび操作するためのコマンド ライン引数の受け渡し

以下は、コマンドライン引数で動作するプログラムです。

#include <stdio.h>
#include <stdlib.h>

int main (int argc, char *argv[]) {
int i=0;
int d;
float f;
long int l;
FILE *file = NULL;
printf("\ncmdline args count=%d", argc);

/* First argument is executable name only */
printf("\nexe name=%s", argv[0]);

for (i=1; i< argc; i++) {
    printf("\narg%d=%s", i, argv[i]);
 }

/* Conversion string into int */
d = atoi(argv[1]);
printf("\nargv[1] in intger=%d",d);

/* Conversion string into float */
f = atof(argv[1]);
printf("\nargv[1] in float=%f",f);

/* Conversion string into long int */
l = strtol(argv[2], NULL, 0);
printf("\nargv[2] in long int=%ld",l);

/*Open file whose path is passed as an argument */
file = fopen( argv[3], "r" );

/* fopen returns NULL pointer on failure */
if ( file == NULL) {
    printf("\nCould not open file");
  }
else {
    printf("\nFile (%s) opened", argv[3]);
    /* Closing file */
    fclose(file);
  }

printf("\n");
return 0;
}

上記のプログラムの出力を以下に示します。

 $ ./cmdline_strfunc 1234test 12345678 /home/sitaram/test_progs/cmdline/cmdline_strfunc.c
cmdline args count=4
 exe name=./cmdline_strfunc
 arg1=1234test
 arg2=12345678
 arg3=/home/sitaram/test_progs/cmdline/cmdline_strfunc.c
 argv[1] in intger=1234
 argv[1] in float=1234.000000
 argv[2] in long int=12345678
 File (/home/sitaram/test_progs/cmdline/cmdline_strfunc.c) opened

上記の出力では、コマンド ライン引数をプログラムで操作できることがわかります。すべての引数は、プログラムに示されているように、integer、float、long に変換できる文字列として取得されます。プログラムからファイルへの処理操作で使用できる任意のファイルのパスとして渡された場合、任意の文字列でさえ、そのファイルです。上記のプログラムを見ると、(/home/sitaram/test_progs/cmdline/cmdline_strfunc.c) ファイル パスがコマンド ライン引数として渡され、プログラム内でファイルを開いたり閉じたりするために使用されます。

Getopt() API

コマンド ライン引数について詳しく調べると、非常に強力な API である getopt() があります。これにより、プログラマはコマンド ライン オプションを解析しやすくなります。プログラマーは、必須またはオプションのコマンド ライン オプションのリストを getopt() に渡すことができます。プログラムが予期するコマンドラインオプションに従って、コマンドラインオプションが有効か無効かを判断できます。 「optarg、optopt、opterr」のような getopt() 固有の内部変数はほとんどありません

  • オプターグ :コマンドラインの有効なオプションの引数へのポインタを含みます
  • オプト :必須のコマンド ライン オプションがない場合、コマンド ライン オプションが含まれます
  • Opterr :無効なオプションが指定された場合、または必須のコマンド ライン オプションの値が指定されていない場合は、0 以外に設定します

以下は、コマンド ライン オプションの解析を理解するための基本的なプログラムです。

#include <stdio.h>
#include <unistd.h>

int main (int argc, char *argv[]) {
int opt = 0;
char *in_fname = NULL;
char *out_fname = NULL;

while ((opt = getopt(argc, argv, "i:o:")) != -1) {
    switch(opt) {
    case 'i':
    in_fname = optarg;
    printf("\nInput option value=%s", in_fname);
    break;
    case 'o':
    out_fname = optarg;
    printf("\nOutput option value=%s", out_fname);
    break;
    case '?':
    /* Case when user enters the command as
     * $ ./cmd_exe -i
     */
    if (optopt == 'i') {
    printf("\nMissing mandatory input option");
    /* Case when user enters the command as
     * # ./cmd_exe -o
     */
  } else if (optopt == 'o') {
     printf("\nMissing mandatory output option");
  } else {
     printf("\nInvalid option received");
  }
  break;
 }
 }

printf("\n");
return 0;
 }

上記のプログラムの出力は、コマンド ライン オプションをいくつか組み合わせて以下に示します。

Case1:
$ ./cmdline_getopt -i /tmp/input -o /tmp/output
Input option value=/tmp/input
 Output option value=/tmp/output

Case2:
$ ./cmdline_getopt -i -o /tmp/output
Input option value=-o

Case3:
$ ./cmdline_getopt -i
 ./cmdline_getopt: option requires an argument -- 'i'
Missing mandatory input option

Case4:
$ ./cmdline_getopt -i /tmp/input -o
./cmdline_getopt: option requires an argument -- 'o'
 Input option value=/tmp/input
 Missing mandatory output option

Case5:
$ ./cmdline_getopt -k /tmp/input
 ./cmdline_getopt: invalid option -- 'k'
Invalid option received

上記のプログラムでは、「i」と「o」は、getopt() API を使用するプログラムの必須の入出力コマンド ライン オプションとして使用されます。

上記のプログラムで実行される各ケースの基本的な説明が表示されます:

  • Case1 では、両方の必須コマンド ライン オプションとその引数が提供され、プログラムのスイッチ条件の最初の 2 つのケースで適切に処理されます。
  • ケース 2 では、必須の入力オプションの値が指定されていませんが、getopt() が十分にインテリジェントではなく、「I」コマンド ライン オプションの値として「-o」と見なされていることがわかります。これは getopt() のエラー ケースではありませんが、プログラマー自身がそのようなケースを処理するためのインテリジェンスを追加できます。
  • ケース 3 では、コマンド ライン オプションのみが値なしで指定されており、これは必須オプションであるため、この場合、getopt() は「?」を返し、「optopt」変数が「i」に設定されて、必須入力オプションの値が正しいことを確認します。行方不明。
  • ケース 4 では、必須の出力オプションの値がありません。
  • ケース 5 では、必須またはオプションのコマンド ライン オプションではない、無効なコマンド ライン オプションが指定されています。この場合、getopt() は「?」を返し、optopt は設定されません。これは、getopt() が想定していない未知の文字であるためです。

Linux
  1. Linux Catコマンド:使用法と例

  2. Linux Sedコマンド:使用法と例

  3. Linuxコマンド-概要と例

  1. コマンドライン引数をBashスクリプトに渡しますか?

  2. 6 Expectスクリプトのコマンドライン引数の例

  3. docker run へのコマンドライン引数

  1. Linux nice and reniceコマンドチュートリアル(7例)

  2. Linuxコマンドラインの歴史をマスターするための15の例

  3. Linux でファイルの行数を数える方法 (wc および nl コマンドの例)