GNU/Linux >> Znalost Linux >  >> Linux

C argc a argv Příklady pro analýzu argumentů příkazového řádku

Kdykoli spustíte program na terminálu, můžete předat některé argumenty, které program očekává a které lze použít během provádění programu. Zde systém poskytuje interní zařízení pro udržování všech argumentů předávaných od uživatele při provádění programu. Tyto argumenty jsou známé jako „Argumenty příkazového řádku“.

V tomto tutoriálu zmapujeme porozumění argumentům příkazového řádku s fungujícím programem, abychom mu lépe porozuměli ostrým a jasným způsobem. Než se však pustíme do programu, měli bychom vědět, jak systém poskytuje možnosti argumentů příkazového řádku. Jak víme, každý program v jazyce C musí mít funkci main() a možnost argumentů příkazového řádku zajišťuje samotná funkce main(). Když je uvedeno níže, je v programu použita deklarace a program má schopnost používat/manipulovat argumenty příkazového řádku.

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

Parametr argc je zde počet celkových argumentů příkazového řádku předaných spustitelnému souboru při spuštění (včetně názvu spustitelného souboru jako prvního argumentu). Parametr argv je pole řetězce znaků každého argumentu příkazového řádku předávaného spustitelnému souboru při spuštění. Pokud jste v programování v C noví, měli byste nejprve pochopit, jak pole C funguje.

Níže je uveden pracovní program využívající argument příkazového řádku.

 #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;
 }

Níže je uveden výstup při spuštění programu.

$ ./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

Ve výše uvedeném výstupu můžeme vidět, že celkový počet argumentů je interně udržován parametrem „argc“ main(), který má hodnotu '7' (ve kterém jeden argument je název spustitelného souboru a '6' jsou argumenty předané programu). hodnoty argumentů jsou uloženy v parametru „argv“ main(), což je pole řetězců znaků. Zde funkce main () ukládá každou hodnotu argumentu jako znakový řetězec. Vidíme, že iterováním přes pole „argv“ můžeme získat všechny předané argumenty v programu.

Existuje ještě jedna deklarace funkce main (), která poskytuje přidanou možnost pro práci s proměnnými prostředí uvnitř programu. Stejně jako argumenty udržované v poli argv[], funkce main() má vnitřní zařízení k udržování všech proměnných systémového prostředí v poli znakových řetězců, které lze brát jako parametr funkce main(). Níže je uvedeno prohlášení.

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

Níže je uveden pracovní program používající argument příkazového řádku spolu s proměnnými prostředí.

#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;
}

Výstup výše uvedeného programu je uveden níže.

$ ./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
$

Ve výše uvedeném výstupu můžeme vidět, že všechny systémové proměnné prostředí lze získat třetím parametrem funkce main(), které jsou procházeny v programu a zobrazeny ve výstupu.

Předávání argumentů příkazového řádku k programování a manipulaci s argumenty

Níže je uveden program pracující s argumenty příkazového řádku.

#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;
}

Výstup výše uvedeného programu je uveden níže.

 $ ./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

Ve výše uvedeném výstupu můžeme vidět, že s argumenty příkazového řádku lze v programu manipulovat; všechny argumenty jsou získány jako znakový řetězec, který lze převést na celé číslo, float, dlouhé, jak je uvedeno v programu. Dokonce i jakýkoli řetězec znaků, pokud je předán jako cesta k libovolnému souboru, který může program použít k operaci zpracování souboru tohoto souboru. Ve výše uvedeném programu můžeme vidět, že (/home/sitaram/test_progs/cmdline/cmdline_strfunc.c ) cesta k souboru je předána jako argument příkazového řádku, který se používá uvnitř programu k otevření souboru a zavření souboru.

Getopt() API

Pokud prozkoumáme více argumentů příkazového řádku, máme velmi výkonné API – getopt(). Usnadňuje programátorovi analyzovat možnosti příkazového řádku. Programátor může poskytnout seznam povinných nebo volitelných možností příkazového řádku pro getopt(). Může určit, zda je volba příkazového řádku platná nebo neplatná podle očekávaných možností příkazového řádku programu. Existuje několik interních proměnných specifických pro getopt(), jako je „optarg, optopt, opterr“

  • Optarg :obsahuje ukazatel na argument platné možnosti příkazového řádku
  • Optop :obsahuje možnost příkazového řádku, pokud chybí povinná možnost příkazového řádku
  • Opter :nastaveno na nenulovou hodnotu, pokud je zadána neplatná volba nebo není zadána hodnota povinné volby příkazového řádku

Níže je uveden základní program pro pochopení analýzy možností příkazového řádku.

#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;
 }

Výstup výše uvedeného programu je uveden níže s několika kombinacemi voleb příkazového řádku:

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

Ve výše uvedeném programu jsou „i“ a „o“ brány jako povinné vstupní a výstupní možnosti příkazového řádku pro program využívající getopt() API.

Nyní bychom měli základní vysvětlení každého případu provedeného ve výše uvedeném programu:

  • V případě 1 jsou k dispozici obě povinné možnosti příkazového řádku s jejich argumenty, které jsou správně zpracovány v prvních dvou případech stavu přepínače programu.
  • V případě 2 není zadána hodnota povinného vstupu, ale vidíme, že getopt() není dostatečně inteligentní a považuje „-o“ za hodnotu „I“ možnosti příkazového řádku. Není to případ chyby pro getopt(), ale programátor může sám přidat inteligenci, aby takový případ zvládl.
  • V případě Case3 je zadána pouze možnost příkazového řádku bez její hodnoty a toto je povinná možnost, takže v tomto případě by getopt() vrátilo '?' a proměnná „optopt“ je nastavena na 'i', aby se potvrdilo, že hodnota povinného vstupu je chybí.
  • V případě 4 chybí hodnota povinného výstupu.
  • V případě Case5 je uvedena neplatná volba příkazového řádku, která není povinná ani volitelná. V tomto případě funkce getopt() vrátila ‚?‘ a optopt není nastaven, protože jde o neznámý znak, který funkce getopt() neočekává.

Linux
  1. Linux Cat Command:Použití a příklady

  2. Příkaz Linux Sed:Použití a příklady

  3. 15 Příklady pro zvládnutí historie příkazového řádku Linuxu

  1. Jak počítat počet řádků v souboru v Linuxu (příklady wc a nl)

  2. Příklady příkazů mkdir a rmdir v Linuxu

  3. Příklady příkazů swapon a swapoff v Linuxu

  1. Linux nice and renice Command Tutorial (7 příkladů)

  2. Linuxové příkazy – přehled a příklady

  3. Předat argumenty příkazového řádku skriptu Bash?