-
Shell編程
鎖定
shell 是操作系統的最外層。shell 合併編程語言以控制進程和文件,以及啓動和控制其它程序。shell 通過提示您輸入,向操作系統解釋該輸入,然後處理來自操作系統的任何結果輸出來管理您與操作系統之間的交互。
- 外文名
- shell
- 類 別
- 操作系統
- 應 用
- 編程技術
- 常 見
- 在ARM技術裏有很廣的應用
目錄
- ▪ 第2章 變量
- ▪ 第3章 循環結構與流程控制
- ▪ 第4章 函數
- ▪ 第5章 算術運算
- ▪ 第6章 重定向與轉向
- ▪ 第7章 高級變量與字符串操作
- ▪ 第8章 正則表達式
- ▪ 第9章 sed編輯器
Shell編程基本概述
shell 提供了與操作系統通信的方式。此通信以交互的方式(來自鍵盤的輸入立即操作)或作為一個 shell 腳本執行。shell 腳本是 shell 和操作系統命令的序列,它存儲在文件中。
當登錄到系統中時,系統定位要執行的 shell 的名稱。在它執行之後,shell 顯示一個命令提示符。普通用户的此提示符通常是一個 $(美元符)。當提示符下輸入命令並按下 Enter 鍵時,shell 對命令進行求值,並嘗試執行它。取決於命令説明,shell 將命令輸出寫到屏幕或重定向到輸出。然後它返回命令提示符,並等待您輸入另一個命令。
命令行是輸入所在的行。它包含 shell 提示符。每行的基本格式如下:
$ 命令參數(一個或多個)
shell 視命令行的第一個字(直到第一個空白空格)為命令,所有後繼字為自變量。
在Windows環境下,不論是使用Visual C++還是Delphi或是其他一些軟件開發工具開發的應用程序,儘管存在着差別,但有一點是相同的:都是運行於Windows操作系統之下的。在程序開發過程中也經常要在自己的應用程序中加入一些Windows系統本身就有的功能,比如文件的拷貝、刪除、查找以及運行程序等等。而這些功能在Windows操作系統下都是具備的,顯然如果能直接從系統中調用這些功能將不僅僅減少程序的大小和開發人員的工作量,而且由於是直接通過操作系統來完成這些功能,將會大大減小這部分程序出現異常錯誤的概率。Windows系統雖説也存在不少錯誤,但常用功能的錯誤還是比較少的,而且通過補丁程序可以更低限度減少系統錯誤,因此程序員可以將調試檢錯的注意力放在應用程序的其他地方,對於調用系統功能這部分代碼則可以不必投入太大的精力去調試,因為這部分調試的工作在操作系統發佈的時候就已經由微軟做好了。本文通過外殼編程,實現了搜尋文件、運行程序、控制工具條、最大最小化窗口的功能。
Shell編程實現方法
前面所説的直接使用Windows操作系統部分功能的編程方法就是針對Windows操作系統外殼的編程,可以通過對操作系統提供的幾個編程接口對操作系統的部分功能進行調用,甚至可以按照自己的意圖在應用程序中對部分功能進行修改、擴展。但這方面的資料介紹不是特別多,講的也大都語焉不詳,而且用通常的編程方法去進行外殼編程是非常麻煩的,動輒就要對相關的結構對象進行設置,而這樣的結構裏的數據成員少則十來個多則幾十個,因此配置起來非常煩瑣,下面就以一個比較簡單的外殼操作--拷貝文件進行舉例説明:
…… SHFILEOPSTRUCT FileOp; //外殼的文件操作結構 FileOp.hwnd=m_hWnd; //設置句柄 //設置操作方式,拷貝用FO_COPY,刪除用 FO_DELETE FileOp.wFunc=FO_COPY; FileOp.pFrom=m_source; //源文件路徑 FileOp.pTo=m_detect; //目標文件路徑 FileOp.fFlags=FOF_ALLOWUNDO; //允許恢復 FileOp.hNameMappings=NULL; FileOp.lpszProgressTitle=strTitle; //設置標題 SHFileOperation(&FileOp); //執行外殼拷貝 if(FileOp.fAnyOperationsAborted) //監測有無中止 TRACE("An Operation was aborted!!!\n"); …… |
上述代碼實現起來雖然效果還是不錯的,但然實現起來卻是比較麻煩的,這僅僅是一個比較簡單的外殼操作,對於一些比較複雜的外殼操作比如系統托盤、任務條等等的編程,更是尤為嚴重,而且象此類編程,MFC裏並沒有提供封裝好的程序類庫,提供的只有系統的WinAPI 應用程序接口,因此在程序開發過程中往往會有一種在進行SDK編程的感覺。
COM (Component Object Model,組件對象模型)是Microsoft創建的一種二進制和網絡標準,也是Microsoft大力推廣並已取得廣泛認可的一種組件標準。在COM標準中,COM對象被很好的封裝起來,客户無法訪問對象的實現細節,提供給用户的訪問途徑是通過COM接口來訪問。對於COM接口有兩方面的含義:首先它是一組可供調用的函數,由此客户可以讓該對象做某些事情;其次,也是更為重要的,接口是組件及其客户程序之間的協議。也就是説接口不但定義了可用什麼函數,也定義了當調用這些函數時對象要做什麼。Windows操作系統本身作為一個大的COM組件對象,也提供了一些必要的COM接口給客户程序,因此我們可以通過這些COM接口來直接對Windows外殼進行編程。
在程序進行正式編寫設計之前有一點是肯定的:程序裏需要用到COM接口,要對COM對象進行操作。因此首先要加入初始化COM和終止COM的代碼。一般是在應用程序類的InitInstance()函數的開始處和返回前添加初始化COM和終止COM代碼的:
…… CoInitialize(NULL); //初始化COM …… CoUninitialize(); //終止COM代碼 …… |
以上兩個函數在MFC程序和非MFC程序中都可以很好的使用。另外,如果程序框架是以MFC為基礎的,那麼只需簡單的調用AfxOleInit()函數就可以達到同樣的目的。而且不必顯式調用終止COM的代碼。在COM標準中,訪問COM對象的途徑是COM接口,因此在編寫操縱Windows 系統外殼程序首先要得到其提供的COM接口。所用的COM接口是IShellDispatch,它是從IDispatch接口派生來的,在VC安裝目錄的VC98\Include\Exdisp.h頭文件中有定義,下面節選了一些將要用到的接口定義:
…… EXTERN_C const IID IID_IShellDispatch; #if defined(__cplusplus) && !defined(CINTERFACE) interface DECLSPEC_UUID("D8F015C0-C278-11CE-A49E-444553540000") IShellDispatch : public Idispatch { public: …… virtual HRESULT STDMETHODCALLTYPE MinimizeAll( void) = 0; virtual HRESULT STDMETHODCALLTYPE UndoMinimizeALL( void) = 0; virtual HRESULT STDMETHODCALLTYPE FileRun( void) = 0; virtual HRESULT STDMETHODCALLTYPE CascadeWindows( void) = 0; virtual HRESULT STDMETHODCALLTYPE TileVertically( void) = 0; virtual HRESULT STDMETHODCALLTYPE TileHorizontally( void) = 0; virtual HRESULT STDMETHODCALLTYPE ShutdownWindows( void) = 0; virtual HRESULT STDMETHODCALLTYPE Suspend( void) = 0; virtual HRESULT STDMETHODCALLTYPE SetTime( void) = 0; virtual HRESULT STDMETHODCALLTYPE TrayProperties( void) = 0; virtual HRESULT STDMETHODCALLTYPE Help( void) = 0; virtual HRESULT STDMETHODCALLTYPE FindFiles( void) = 0; virtual HRESULT STDMETHODCALLTYPE FindComputer( void) = 0; }; …… |
該接口在CoCreateInstance()函數創建COM對象時將會得到指向其的指針,通過這個函數客户程序可以避免顯式同類廠打交道,其實該函數內部也調用了CoGetClassObject()函數來獲取COM對象的類廠,只不過它把通過類廠創建對象的過程封裝起來了,只需用户指定對象類的CLSID和待輸出的接口指針及接口ID,顯然這樣直接創建COM對象是非常便捷的,在獲取到COM對象指針之後就可以通過這個指針去訪問調用COM對象裏的方法來實現Windows 外殼的種種功能調用了。下面是實現該功能的部分關鍵代碼:
…… HRESULT sc;//返回結果 IShellDispatch *pShellDisp = NULL; //初始化接口指針 //直接創建COM對象 sc = CoCreateInstance( CLSID_Shell,//指定待創建的COM對象標識符 NULL, //指定被聚合時的外部對象的接口指針 CLSCTX_SERVER, //指定組件類別,可以指定進程內組件進程外組件或者進程內控制對象。 IID_IDispatch, //指定接口ID,需要注意的是這裏指的是待 //創建的COM對象的接口ID,而非類廠對象的接口標識符 (LPVOID *) &pShellDisp );//存放函數返回的對象的接口指針 /* 在上述代碼中,CoCreateInstance首先調用CoGetClassObject函數創建類廠對象,然後用得到的類廠對象的接口指針創建真正的COM對象,最後把類廠對象釋放並返回,這樣就很好的把類廠屏蔽起來,使用户用起來更為簡單。*/ if( FAILED(sc) )//必須用FAILED 或SUCCECCED來判斷COM對象是否創建成功 return; pShellDisp->FindFiles(); //調用COM對象裏的方法 pShellDisp->Release(); //釋放申請到的接口指針 …… |
在這裏通過pShellDisp接口指針調用了COM對象的FindFiles()方法去進行查找文件的系統外殼操作。同樣,可以根據實際需要靈活調用響應的方法來執行相應的外殼操作,主要有以下幾個方法:MinimizeAll:所有窗口最小化、UndoMinimizeALL:恢復窗口最小化、 FileRun:開始菜單的"運行…"、CascadeWindows:層疊窗口、TileVertically:垂直平鋪、TileHorizontally:水平平鋪、ShutdownWindows:關閉Windows、Suspend 掛起計算機、SetTime:設定時間、TrayProperties:任務欄屬性、Help Windows:幫助、FindFiles:查找文件、FindComputer:查找計算機等。
這些接口均在VC安裝目錄的VC98\Include\Exdisp.h頭文件中有定義,可以通過對該文件的查看來編寫響應的外殼操作代碼。
Shell編程編程步驟
1、 啓動Visual C++6.0,生成一個Win32應用程序,項目命名為"Shell";
2、 添加應用程序圖標資源APP_ICON和對話框資源DLG_MAIN,對話框界面按上圖一設計;
3、 使用Class Wizard為對話框上的各個按鈕添加鼠標單擊處理函數;
4、 添加代碼,編譯運行程序。
Shell編程常用技巧
1. 字符串的截取
shell字符串的截取的問題:
一、Linux shell 截取字符變量的前8位,有方法如下:
1) expr substr “$a” 1 8
2) echo $a|awk ‘{print substr(,1,8)}’
3) echo $a|cut -c1-8
4) expr $a : ‘\(.\\).*’
5) echo $a|dd bs=1 count=8 2>/dev/null
二、按指定的字符串截取
1) 第一種方法:
${varible##*string} 從左向右截取最後一個string後的字符串
${varible#*string}從左向右截取第一個string後的字符串
${varible%%string*}從右向左截取最後一個string後的字符串
${varible%string*}從右向左截取第一個string後的字符串
“*”只是一個通配符可以不要
例子:
$ MYVAR=foodforthought.jpg
$ echo ${MYVAR##*fo}
rthought.jpg
$ echo ${MYVAR#*fo}
odforthought.jpg
2) 第二種方法:${varible:n1:n2}:截取變量varible從n1到n2之間的字符串。
可以根據特定字符偏移和長度,使用另一種形式的變量擴展,來選擇特定子字符串。試着在 bash 中輸入以下行:
$ EXCLAIM=cowabunga
$ echo ${EXCLAIM:0:3}
cow
$ echo ${EXCLAIM:3:7}
abunga
這種形式的字符串截斷非常簡便,只需用冒號分開來指定起始字符和子字符串長度。
三、按照指定要求分割:
比如獲取後綴名
ls -al | cut -d “.” -f2
2. 大小寫轉換
echo $uppercase |tr [A-Z] [a-z]
echo $lowercase |tr [a-z] [A-Z]
Shell編程編程過程
///////////////////////////////////// #define INC_OLE2 #define WIN32_LEAN_AND_MEAN #define STRICT #include <windows.h> #include <windowsx.h> #include <commctrl.h> #include <shlguid.h> #include <exdisp.h> #include “taskbar.h” #include “resource.h” // data static WNDPROC g_pfnOldProc; static HWND g_hwndButton=NULL; static HWND g_hDlg=NULL; static HINSTANCE g_hInstance; static HICON g_hIconLarge; static HICON g_hIconSmall; // functions static VOID OnRunPrograms( VOID ); static VOID OnFindFiles( VOID ); static VOID OnMinimizeAll( VOID ); static VOID OnUndoMinimize( VOID ); static VOID OnTaskbarProperties( VOID ); static VOID OnAddTab( HWND ); static VOID OnDeleteTab( VOID ); static VOID OnInitDialog( HWND ); static VOID OnButtonActivation( VOID ); // callbacks LRESULT CALLBACK APP_DlgProc( HWND, UINT, WPARAM, LPARAM ); LRESULT CALLBACK ButtonProc( HWND, UINT, WPARAM, LPARAM ); INT APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevious, LPSTR lpsz, INT iCmd ) { BOOL b; g_hIconLarge = (HICON) LoadImage( hInstance, “APP_ICON”, IMAGE_ICON, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CXICON), 0 ); g_hIconSmall = (HICON) LoadImage( hInstance, “APP_ICON”, IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CXSMICON), 0 ); // initialize OLE libraries CoInitialize(NULL); InitCommonControls(); // run main dialog g_hInstance = hInstance; b = DialogBox( hInstance, “DLG_MAIN”, NULL, (DLGPROC)APP_DlgProc ); // exit DestroyIcon( g_hIconLarge ); DestroyIcon( g_hIconSmall ); // free the objects used by ITaskbarList DestroyWindow( g_hwndButton ); OnDeleteTab(); CoUninitialize(); return b; }LRESULT CALLBACK APP_DlgProc( HWND hDlg, UINT uiMsg, WPARAM wParam, LPARAM lParam ) { switch( uiMsg ) { case WM_INITDIALOG: OnInitDialog( hDlg ); break; case WM_COMMAND: switch( wParam ) { case IDC_FINDFILES: OnFindFiles(); return 1; case IDC_RUNPROGRAMS: OnRunPrograms(); return 1; case IDC_MINIMIZE: OnMinimizeAll(); return 1; case IDC_UNDOMINIMIZE: OnUndoMinimize(); return 1; case IDC_PROPERTIES: OnTaskbarProperties(); return 1; case IDC_ADDTAB: OnAddTab( hDlg ); return 1; case IDC_DELETETAB: OnDeleteTab(); return 1; case IDCANCEL: EndDialog( hDlg, FALSE ); return 0; } break; } return 0; } VOID OnFindFiles( VOID ) { HRESULT sc; IShellDispatch *pShellDisp = NULL; sc = CoCreateInstance( CLSID_Shell, NULL, CLSCTX_SERVER, IID_IDispatch, (LPVOID *) &pShellDisp ); if( FAILED(sc) ) return; pShellDisp->FindFiles(); pShellDisp->Release(); return; } VOID OnTaskbarProperties( VOID ) { HRESULT sc; IShellDispatch *pShellDisp = NULL; sc = CoCreateInstance( CLSID_Shell, NULL, CLSCTX_SERVER,IID_IDispatch, (LPVOID *) &pShellDisp ); if( FAILED(sc) ) return; pShellDisp->TrayProperties(); pShellDisp->Release(); return; } VOID OnRunPrograms( VOID ) { HRESULT sc; IShellDispatch *pShellDisp = NULL; sc = CoCreateInstance( CLSID_Shell, NULL, CLSCTX_SERVER, IID_IShellDispatch, (LPVOID *) &pShellDisp ); if( FAILED(sc) ) return; pShellDisp->FileRun(); pShellDisp->Release(); return; } VOID OnMinimizeAll( VOID ) { HRESULT sc; IShellDispatch *pShellDisp = NULL; sc = CoCreateInstance( CLSID_Shell, NULL, CLSCTX_SERVER, IID_IDispatch, (LPVOID *) &pShellDisp ); if( FAILED(sc) ) return; pShellDisp->MinimizeAll(); pShellDisp->Release(); return; } VOID OnUndoMinimize( VOID ) { HRESULT sc; IShellDispatch *pShellDisp = NULL; sc = CoCreateInstance( CLSID_Shell, NULL, CLSCTX_SERVER, IID_IDispatch, (LPVOID *) &pShellDisp ); if( FAILED(sc) ) return; pShellDisp->UndoMinimizeALL(); pShellDisp->Release(); return; } VOID OnInitDialog( HWND hDlg ) { // set the icons (T/F as to Large/Small icon) g_hDlg = hDlg; SendMessage( hDlg, WM_SETICON, FALSE, (LPARAM)g_hIconSmall ); SendMessage( hDlg, WM_SETICON, TRUE, (LPARAM)g_hIconLarge ); } VOID OnAddTab( HWND hWnd ) { static BOOL g_bFirstTime=TRUE; HRESULT sc; ITaskbarList *pDisp = NULL; sc = CoCreateInstance( CLSID_TaskbarList, NULL, CLSCTX_SERVER, IID_ITaskbarList, (LPVOID *) &pDisp ); if( FAILED(sc) ) return; // call the first time only if( g_bFirstTime ) { g_bFirstTime = FALSE; pDisp->HrInit(); // create a new button window g_hwndButton = CreateWindow( “button”, “My Button”, WS_CLIPSIBLINGS|BS_PUSHBUTTON,0, 0, 58, 14, hWnd, NULL, g_hInstance, NULL ); g_pfnOldProc = (WNDPROC) SubclassWindow( g_hwndButton, ButtonProc ); } pDisp->AddTab( g_hwndButton ); pDisp->Release(); return; } VOID OnDeleteTab( VOID ) { HRESULT sc; ITaskbarList *pDisp = NULL; sc = CoCreateInstance( CLSID_TaskbarList, NULL, CLSCTX_SERVER, IID_ITaskbarList, (LPVOID *) &pDisp ); if( FAILED(sc) ) return; pDisp->DeleteTab( g_hwndButton ); pDisp->Release(); return; } LRESULT CALLBACK ButtonProc( HWND hwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam ) { switch( uiMsg ) { case WM_NCACTIVATE: if( wParam==TRUE ) OnButtonActivation(); break; } return CallWindowProc( g_pfnOldProc, hwnd, uiMsg, wParam, lParam ); } VOID OnButtonActivation( VOID ) { HMENU hmenu; RECT r; LONG x, y; // get some window handles HWND h0=FindWindow(“Shell_TrayWnd”, NULL ); HWND h1=FindWindowEx(h0,NULL,”RebarWindow32″, NULL); HWND h2=FindWindowEx(h1,NULL,”MSTaskSwWClass”, NULL); HWND h3=FindWindowEx(h2,NULL,”SysTabControl32″, NULL); GetWindowRect( h3, &r ); // get the currently selected button and // create a new popup menu hmenu = CreatePopupMenu(); INT i=TabCtrl_GetCurSel( h3 ); if( i==-1 ) { AppendMenu( hmenu, MF_STRING, IDC_DELETETAB,”&Close” ); } else { AppendMenu( hmenu, MF_STRING, IDC_MINIMIZE,”&Minimize All” ); AppendMenu( hmenu, MF_STRING, IDC_UNDOMINIMIZE,”&Undo Minimize All” ); AppendMenu( hmenu, MF_SEPARATOR, 0, NULL ); AppendMenu( hmenu, MF_STRING, IDC_PROPERTIES,”&Taskbar Properties” ); } // set and immediately reset its size to get // the current width and height LONG l = TabCtrl_SetItemSize( h3, 0, 0 ); TabCtrl_SetItemSize( h3, LOWORD(l), HIWORD(l) ); // have the menu to appear just above the button if( i==-1 ) { POINT pt; GetCursorPos( &pt ); x = pt.x; y = pt.y; } else { x = r.left + LOWORD(l)*i+3; y = GetSystemMetrics(SM_CYSCREEN)-(HIWORD(l)+1); } TrackPopupMenu( hmenu, TPM_BOTTOMALIGN, x, y, 0, g_hDlg, 0); DestroyMenu( hmenu ); return; } |
Shell編程課程大綱
Shell編程第1章 簡介及基礎
shell簡介及基礎
- shell是什麼,為什麼要學習shell
- shell發展史及分類
- bash功能簡介
- 部署設置bash環境
- shell腳本組成、運行模式及執行方法
- bash排錯方法
- 父shell和子shell
- 常用快捷鍵
Shell編程第2章 變量
- 變量分類
- 內部變量
- 預定義變量
- 自定義變量及基本用法
- 數組
- 特殊字符
- 別名
- Here Document
- 打印特殊字符
Shell編程第3章 循環結構與流程控制
- if條件判斷
- case條件判斷
- for循環
- while循環
- until循環
- select命令
- break和continue
Shell編程第4章 函數
- 函數用法
- 函數作用範圍
- 參數使用
- 建立函數庫
- 遞歸函數
Shell編程第5章 算術運算
- 算術式簡介
- 算術擴展
- 利用expr做算術運算
- 使用$[]做算術運算
- 使用內置變量declare、let做算術運算
- 利用bc做浮點運算
- 進制轉換
Shell編程第6章 重定向與轉向
- 文件代碼
- 操作文件
- 輸入輸出轉向
- 轉向附加
- 標準錯誤伴隨輸出轉向
- Here Document轉向
Shell編程第7章 高級變量與字符串操作
- 變量擴展:測試存在性及空值
- 變量擴展:取字符串切片,字符串長度
- 變量擴展:對比樣式
- 變量擴展:取變量名稱列表,數組索引列表
- 命令替換
Shell編程第8章 正則表達式
- 入門介紹
- 元字符
- 字條轉義
- 重複
- 字符類
- 分支條件
- 反義
- 分組
- 後向引用
- 零寬斷言與負向零寬斷言
- 貪婪與懶惰
- 註釋
- 處理選項
- 平衡組/遞歸匹配
Shell編程第9章 sed編輯器
- sed介紹
- sed基本語法
- sed調用方式
- sed高級用法
Shell編程第10章 awk學習
- awk原理介紹
- awk基本語法
- awk調用方式
- awk循環語句
- awk函數
- awk數組
- awk的BEGIN和END模式
- awk數學運算和字符串操作
- awk重定向輸出
- awk與bash之間傳參調用
- awk調試方法
Shell編程第11章 文字與圖形接口編程
- dialog文本接口編程
- xdialog圖形接口編程
Shell編程第12章 bash網絡編程
- bash網絡轉向
- 遠程執行命令
- expect與自動登錄
Shell編程第13章 trap陷阱觸發
- 信號signal
- trap運用
Shell編程第14章 shell腳本加密與包裝
- 加密shell腳本
- 生成二進制可執行文件
Shell編程第15章 shell中常用命令介紹
- grep命令詳解
- find與xargs
- sort和uniq命令詳解
- cut命令詳解
- curl與wget命令詳解
- cat、tac與rev
- tr命令詳解
- paste命令詳解
- join命令詳解
Shell編程第16章 一些shell技巧
- 利用腳本修改密碼
- 判斷奇偶
- 添加行號與刪除行號
- 刪除行首空格,刪除重複行
- 合併行操作
- 逐行讀取操作
- 字符與ASCII碼轉換操作
- 連接mysql數據庫操作
Shell編程第17章 shell十三問
- PS1和CR的關係
- echo知多少
- “”(雙綽號)與”(單引號)差在哪兒
- export前後差在哪兒
- exec跟source差在哪兒
- ()與{}差在哪兒
- $(())和$()、${}差在哪兒
- $@和$*差在哪兒
- &&和||差在哪兒
- >和<差在哪兒
- 你要if還是case
- for what?while和until差在哪兒?
- [^ ]和[! ]差在哪兒
Shell編程第18章 綜合實戰講解一
- 系統信息收集腳本
- 備份腳本
- 日誌切割腳本
- nagios監控插件腳本
- 發郵件腳本
Shell編程第19章 綜合實戰講解二
- 系統初始化腳本
- 基礎軟件安裝腳本
- iptables腳本
- 線上操作記錄審核腳本
- 文本完整性審核腳本
- kickstart配置腳本