1. 程式人生 > >Google gflags庫(解析命令列引數)

Google gflags庫(解析命令列引數)

google gflags是google使用的一個開源庫,用於解析命令列標記。目前的gflags有C++和Python兩個版本。本文主要介紹gflags的C++版本使用方法。

命令列標記是指使用者在執行可執行程式時,在命令列中指定的引數。例如,對於命令:

  1. fgrep -l -f /var/tmp/foo johannes brahms  

-l-f /var/tmp/foo是兩個命令列標記,而johnnesbrahms則是命令列引數。一個應用往往具有許多個命令列標記,對應這些標記,可以傳入一些由使用者指定的引數。例如,在上面的例子中,-l標記沒有任何引數,而-f標記的引數則是/var/tmp/foo

這些標記和引數儲存在main函式的argcargv引數中。一般而言,main函式總有如下的形式:

  1. int main(int argc, char ** argv) {…}  

其中argc指明瞭argv陣列的長度,而argv陣列則空格為分割,儲存命令列後用戶輸入的引數。在GNU C Library中,這個工作主要是由getopt函式來完成的。以下是getopt函式的一個例子:

  1. #include <ctype.h>
  2.  #include <stdio.h>
  3.  #include <stdlib.h>
  4.  #include <unistd.h>
  5.  int
  6.  main (int argc, char **argv)  
  7.  {  
  8.    int aflag = 0;  
  9.    int bflag = 0;  
  10.    char *cvalue = NULL;  
  11.    int index;  
  12.    int c;  
  13.    opterr = 0;  
  14.    while ((c = getopt (argc, argv, "abc:")) != -1)  
  15.      switch (c)  
  16.        {  
  17.        case'a':  
  18.          aflag = 1;  
  19.          break;  
  20.        case
    'b':  
  21.          bflag = 1;  
  22.          break;  
  23.        case'c':  
  24.          cvalue = optarg;  
  25.          break;  
  26.        case'?':  
  27.          if (optopt == 'c')  
  28.            fprintf (stderr, "Option -%c requires an argument.\n", optopt);  
  29.          elseif (isprint (optopt))  
  30.            fprintf (stderr, "Unknown option `-%c'.\n", optopt);  
  31.          else
  32.            fprintf (stderr,  
  33.                     "Unknown option character `\\x%x'.\n",  
  34.                     optopt);  
  35.          return 1;  
  36.        default:  
  37.          abort ();  
  38.        }  
  39.    printf ("aflag = %d, bflag = %d, cvalue = %s\n",  
  40.            aflag, bflag, cvalue);  
  41.    for (index = optind; index < argc; index++)  
  42.      printf ("Non-option argument %s\n", argv[index]);  
  43.    return 0;  
  44.  }  

 在這個例子中可以看出,所有的標記的定義都必須要集中在一個地方處理(也就是switch程式碼段中)。而gflags則與getopt函式不同,在gflags中,標記的定義分散在原始碼中,不需要列舉在一個地方。這意味著單個的原始碼檔案可以定義他們自己所使用的標記,一切連線到這個檔案的應用將獲取這個標記,並且gflags將自動對這個標記進行適當的處理。這對於軟體的靈活性及程式碼的重用是很有好處的。當然,這也產生了一定的風險,特別是,兩個不同的檔案可能會定義擁有同一個名字的命令列標記,在平常的情況下沒有問題,但當這兩個檔案被同一個二進位制程式連線的時候,就會出現錯誤。

gflags使用C++語言實現,其風格也是C++風格的。本文的其餘部分介紹瞭如何使用gflags。

一、如何定義一個命令列標記

使用gflags需要引用gflags標頭檔案:

#include <gflags/gflags.h>

在gflags.h檔案的結尾,定義了一些標記定義巨集,因此在引用了gflags.h後,定義一個命令列標記就變得十分簡單了。如,在foo.cc檔案的開頭,我們引入如下的命令列標記的定義:

  1. #include <gflags/gflags.h>
  2. DEFINE_bool(big_menu, true"Include 'advanced' options in the menu listing");  
  3. DEFINE_string(languages, "english,french,german”,"comma-separated list of languages to offer in the 'lang' menu");  

在這段程式碼中,我們定義了兩個命令列標記:bool型的big_menu,以及string型的language。所有的DEFINE巨集都有三個引數:標記的名字,預設值,以及針對這個標記的說明。第三個引數是非常有用的,尤其是在構建大型程式的時候,在命令列中使用—help標記可以列出被gflags所定義的所有標記的型別、預設值及對其的說明(也就是巨集第三個引數)。

DEFINE巨集支援的型別包括:

o    DEFINE_bool: boolean

o    DEFINE_int32: 32-bit integer

o    DEFINE_int64: 64-bit integer

o    DEFINE_uint64: unsigned 64-bit integer

o    DEFINE_double: double

o    DEFINE_string: C++ string

可以在可執行程式的任何一個原始檔中定義一個標記,而針對每個標記,只需要定義一次。如果想要在不同的原始檔中訪問該標記,可以使用DECLARE巨集來宣告這個標記(其實就是聲明瞭一個extern變數的引用)。一個更好的方法是,對於一個標記,可以在foo.cc中定義它,並且在foo.h中宣告它。這樣,包含了foo.h的所有原始檔都可以引用這個標記。

二、如何訪問一個標記

訪問標記較為簡單。只要對標記進行了定義或者宣告,那麼只需要在使用它的地方加上字首“FLAGS_”就可以引用這個標記了。如,

  1. if (FLAGS_consider_made_up_languages)  
  2. FLAGS_languages += ",klingon";   // implied by --consider_made_up_language
  3. if (FLAGS_languages.find("finnish") != string::npos)  
  4.      HandleFinnish();  

三、在命令列中使用標記

對於上面的foo.cc和foo.h,如果其編譯後產生的二進位制檔案為app_containing_foo,則在命令列中設定這些標記的方法為:

app_containing_foo --nobig_menu -languages="chinese,japanese,korean" …

這個命令會把big_menu設定為false,並且將language設定為“chinese,japanese,Korean”。對於string、int、double等型別的標記,設定標記時使用如下形式:

o    app_containing_foo --languages="chinese,japanese,korean"

o    app_containing_foo -languages="chinese,japanese,korean"

o    app_containing_foo --languages "chinese,japanese,korean"

o    app_containing_foo -languages "chinese,japanese,korean"

這些方式是等價的。但注意gflags不支援短標記與合併標記。如ls –la這種型別,是不能夠被gflags處理的。這和getopt函式有所不同。

 需要注意的還有以下幾點:

1,--連用會終止標記。如命令:foo -f1 1 -- -f2 2,則f2標記將不被處理;

2,bool型的標記,如big_menu,既可以使用—big_menu=true/false,也可以使用—big_menu/--nobig_menu這種方式。gflags都可以解析。

3,使用未被定義的標記將引發嚴重錯誤。

四、在程式中解析標記

在程式中解析標記可以使用如下函式:

  1. google::ParseCommandLineFlags(&argc, &argv, true);  

注意argc和argv均以地址方式傳遞,也就是該函式可以改變argc和argv的內容。通常這段程式碼會出現在main函式的開始。最後一個引數是移除標記,它指明瞭是否將被gflags成功解析的標記從引數列表中移除。例如,對於命令列:

foo –options=start file1 file2

在這個命令列中,options是一個命令列標記,將被gflags解析(如果它已經被定義了);而file1和file2則是命令列引數。如果設定remove標記位ture,則—options=start會在呼叫ParseCommandLineFlags後被移除,此時argc=2,而argv中則儲存了file1和file2兩個引數。如果remove標記位設為false,則—options=start將不會被移除,則argc不會改變,但argv會重新排列,將所有的標記排列在前面。

學習資料參考於:

<<用Google的gflags優雅的解析命令列引數>>

http://www.leoox.com/?p=270

<<google gflag使用指南>>

http://blog.csdn.net/starays/article/details/7990984

相關推薦

Google gflags解析命令引數

google gflags是google使用的一個開源庫,用於解析命令列標記。目前的gflags有C++和Python兩個版本。本文主要介紹gflags的C++版本使用方法。 命令列標記是指使用者在執行可執行程式時,在命令列中指定的引數。例如,對於命令: fgre

Googlegflags優雅的解析命令引數(一)

寫了這麼多年的Linux下C/C++程式碼,一直使用getopt_long來解析命令列引數,同時定義一個全域性的struct來儲存各個命令列引數的值。雖然用得比較“繁瑣”,但也安於現狀。最近突然發現了Google早在多年前就開源了一個解析命令列引數的“神器”gflags。趕

get_optlong用法linux解析命令引數

const char * const shor_options = “ho:v” ;struct option 型別陣列該資料結構中的每個元素對應了一個長選項,並且每個元素是由四個域組成。通常情況下,可以按以下規則使用。第一個元素,描述長選項的名稱;第二個選項,代表該選項是否需要跟著引數,需要引數則為1,反

gflags(google開源的一套命令引數解析工具)

gflags是google開源的一套命令列引數解析工具,比getopt()函式功能要強大,使用起來更加方便,gflags還支援從環境變數和配置檔案中讀取引數。目前有C++和Python版本。本文就來詳細介紹C++版本gflags的使用,主要分如下兩個部分 Cont

FFmpeg 解析命令引數

FFmpeg 命令列基礎語法: ffmpeg [global_options] {[input_file_options] -i input_file}...{[output_file_options] output_file}... global_options:全域性引

go語言解析命令引數的實現

一、實現程式碼如下 // fffggg project main.go package main import (     "flag"     "fmt" ) func main() {     var num int     var mode string   

Python解析命令引數

使用Python編寫應用程式或是指令碼的時候,經常會用到命令列引數。C語言中有庫函式getopt解析短命令列引數,使用getopt_long解析短命令和長命令的組合。 Python使用getopt模組,同時解析短命令和長命令。看具體使用例子 #!/usr/bin/python import sys

linux中getopt_long解析命令引數(附上windows上的getopt_long原始碼)

     getopt_long支援長選項的命令列解析,使用man getopt_long,得到其宣告如下:       #include <getopt.h>       int getopt_long(int argc, char * const argv[

C語言-解析命令引數

#include <stdio.h> #include<unistd.h> /* 函式說明 : int getopt(int argc,char * const argv[ ],const char * optstring);) 用來分析命令

使用 Qt 解析命令引數

Qt解析命令列 我們使用 Python 寫個簡單的指令碼很方便,直接 import argparse 就能很容易的實現命令列引數解析的功能,還可以通過 --help 來輸出幫助功能,而 Qt5 頁提供了這方面的支援。 Qt 從 Qt5.2之後提供了 QCom

getopt、getopt_long和getopt_long_only解析命令引數

一:posix約定:          下面是POSIX標準中關於程式名、引數的約定:          程式名不宜少於2個字元且不多於9個字元;          程式名應只包含小寫字母和阿拉伯數字;          選項名應該是單字元或單數字,且以短橫 ‘-’ 為

3.QT中QCommandLineParser和QCommandLineOption解析命令引數

 1新建專案 main.cpp #include<QCoreApplication> #include<QCommandLineParser>

linux 中解析命令引數(getopt_long用法)

getopt_long支援長選項的命令列解析,使用man getopt_long,得到其宣告如下:   #include <getopt.h>   int getopt_long(int argc, char * const argv[],   const cha

Google開源命令引數解析gflags

今天寫程式時需要寫一個命令列解析程式,於是網上搜索getopt()的實現程式碼,但搜到的資訊基本上是如何使用getopt(),而系統又是Windows的;於是想到了以前專案中使用到的Google開源命令列解析庫gflags。 google開源的gflags是一套命令列引數解析工具,他可以替代getopt

Apollo程式碼解析:3. 命令引數傳遞google gflags

簡介 在百度Apollo中gflag被廣泛的應用在各種全域性變數中,例如節點名,變數名,各種狀態標誌中。 gflags 是google開源的一套命令列引數解析工具,比 getopt 功能更加強大,使用起來更加方便。 什麼是 命令列引數解析工具 呢? 這裡拿p

google gflags 處理命令引數

#include <string> #include <iostream> #include <gflags/gflags.h> using namespace std; DEFINE_string(input_path, "empty" , "input f

glib命令解析簡單使用--GOptionEntry 命令引數

轉自:http://blog.csdn.net/ciahi/archive/2010/12/15/6076786.aspx 官網文件為: http://library.gnome.org/devel/glib/stable/glib-Commandline-option-p

linux shell中的命令自動補全compgen complete命令引數解析

很多時候,當我們寫一個指令碼時,我們總會提供一些可選的命令選項。當可選項比較多的時候,比如git, 如果能夠提供命令自動補全,無疑是錦上添花的事。而且個人認為,這種方式,比採用將命令做成選擇選單要更好一些。 假設我們現在這樣一個指令碼,指令碼執行命令時bsu,  類似gi

Sqlmap命令引數解析

前言本文轉載自werner-wiki的部落格,便於參考學習(侵權刪)原文地址:https://blog.csdn.net/wn314/article/details/78872828。一、Sqlmap是什麼Sqlmap是開源的自動化SQL注入工具,由Python寫成,具有如下

MFC解析啟動命令引數——CCommandLineInfo類

MFC中CCommandLineInfo類被用於分析啟動應用時的命令列引數。 MFC應用一般都會在它的應用物件中使用函式InitInstance()建立這個類的一個本地例項。然後把該物件傳給CWinApp::ParseCommandLine(),ParseCommandLine()又重複呼叫