1. 什麼是shell編程啊,求簡單實例
剛剛學習了新書<<實用linux Shell編程>>,書寫的容易懂,第一章就回答了什麼是shell編程的問題。下面簡單回答,僅供參考,謝謝!
1)linux 命令,你可以一條一條執行,例如,顯示日期時間命令是date,顯示當前目錄的命令是pwd,列印一句話的命令可以是echo "good morning"
2)一個腳本是包含多條命令的文本文件,命令將按照順序依次運行。例如z.sh包含4行,如下:
$ cat z.sh
#!/bin/bash
date
pwd
echo "good morning"
第一行為腳本解釋程序的位置/bin/bash, 其他行, 是命令的「堆放」
3)增加腳本執行許可權:
$ chmod +x z.sh
4)運行腳本:
$ z.sh (或者./z.sh)
Mon Jan 12 15:20:32 CST 2015
/home/user
good morning
輸出有3行,分別是命令date的結果,命令pwd的結果,命令echo "good morning"的運行結果。
5)一般地,腳本不單單是幾個簡單命令的「堆放」,有判斷、分支選擇命令,循環命令,參數輸入,函數定義等等。
但是最簡單的shell腳本可以就一條命令,或者就幾個簡單命令的「堆放」。
僅供參考,謝謝!
2. SHELL編程幾個小例子
一個最簡單的 shell 編程例子(假設使用全屏幕編輯程序 vi 編輯、並保存一個文件名為:my_string.sh 的文件):
#!/bin/sh
#print my_string's content in the console window
my_string = "This is my first sentence !"
echo $my_string
其中:# 表示注釋語句,用雙引號引起來的是字元串的內容,my_string 是變數名,$ 表示求變數 my_string 的值,echo 表示將求得的 my_string 的值顯示在控制窗口上。
然後在 SHELL 提示符 $ 下面,輸入:chmod +x my_string.sh <cr> 將該文件的許可權修改為可執行許可權;
$./my_string.sh <cr> 在當前目錄下面執行 my_string.sh SHELL 腳本文件
當然了,UNIX/Linux 系統的 SHELL 功能是極其強大的,如果要想精通 SHELL 編程,還需要學習關於一些 awk、sed 等的使用。所以說想達到輕車熟路的程度也不是一件輕而易舉的事情,是需要經過長時間的上機編程體會的。
3. Shell的簡單編程
$cat test.sh
#!/bin/bash
if [ -c $1 ];then
echo "$1是字元設備文件"
else test -e $1 || echo "This file is not exist"
fi
if test -d $2;then
echo "$2是目錄文件"
for file in `ls $2/*.c`
do
ls -l $file
done
else test -e $2 || echo "This file is not exist"
fi
$./test.sh ddd.c test
test是目錄文件
-rw-rw-r--. 1 flycat flycat 0 1月 1 21:20 test/aaa.c
-rw-rw-r--. 1 flycat flycat 0 1月 1 21:20 test/bbb.c
-rw-rw-r--. 1 flycat flycat 0 1月 1 21:20 test/ccc.c
4. shell編程
先得遍歷目錄,然後根據每一個獲取的文件或目錄來進行判斷,從而進行不同的代碼塊就ok了。
1.得到文件後:判斷文件讀寫熟悉,然後進一步操作
2.判斷文件可執行並且有許可權執行,則直接去執行就行了(考慮參數)。
……
差不多就是這個思路了
5. 幾個Shell編程例子
根據我以前的 SHELL 編程經驗,關於 UNIX/Linux SHELL 編程的詳細例子,這個必須要參考專門的 SHELL 編程指南、以及 awk 等操作才行。因為不同版本的 SHELL 編程(bash、C-Shell、ksh等),其語句也不是完全相同的,它們是有差別的。SHELL 編程中的細節實在是太細了,哪怕思路是正確的,但是在 SHELL 語句中缺少一個符號都不行。
6. 《Linux命令編輯器Shell編程實例大全》pdf下載在線閱讀全文,求百度網盤雲資源
《Linux命令編輯器Shell編程實例大全》網路網盤pdf最新全集下載:
鏈接:https://pan..com/s/1KuGwNJWqX0jvV3RXtMVh4A
7. shell編程(條件判斷舉例)
shell 是操作系統的最外層。shell 合並編程語言以控制進程和文件,以及啟動和控制其它程序。shell 通過提示您輸入,向操作系統解釋該輸入,然後處理來自操作系統的任何結果輸出來管理您與操作系統之間的交互。
外文名
shell
類別
操作系統
應用
編程技術
常見
在ARM技術里有很廣的應用
快速
導航
實現方法
編程步驟
常用技巧
編程過程
課程大綱
基本概述
shell 提供了與操作系統通信的方式。此通信以交互的方式(來自鍵盤的輸入立即操作)或作為一個 shell 腳本執行。shell 腳本是 shell 和操作系統命令的序列,它存儲在文件中。
當登錄到系統中時,系統定位要執行的 shell 的名稱。在它執行之後,shell 顯示一個命令提示符。普通用戶的此提示符通常是一個 $(美元符)。當提示符下輸入命令並按下 Enter 鍵時,shell 對命令進行求值,並嘗試執行它。取決於命令說明,shell 將命令輸出寫到屏幕或重定向到輸出。然後它返回命令提示符,並等待您輸入另一個命令。
命令行是輸入所在的行。它包含 shell 提示符。每行的基本格式如下:
$ 命令參數(一個或多個)
shell 視命令行的第一個字(直到第一個空白空格)為命令,所有後繼字為自變數。
在Windows環境下,不論是使用Visual C++還是Delphi或是其他一些軟體開發工具開發的應用程序,盡管存在著差別,但有一點是相同的:都是運行於Windows操作系統之下的。在程序開發過程中也經常要在自己的應用程序中加入一些Windows系統本身就有的功能,比如文件的拷貝、刪除、查找以及運行程序等等。而這些功能在Windows操作系統下都是具備的,顯然如果能直接從系統中調用這些功能將不僅僅減少程序的大小和開發人員的工作量,而且由於是直接通過操作系統來完成這些功能,將會大大減小這部分程序出現異常錯誤的概率。Windows系統雖說也存在不少錯誤,但常用功能的錯誤還是比較少的,而且通過補丁程序可以更低限度減少系統錯誤,因此程序員可以將調試檢錯的注意力放在應用程序的其他地方,對於調用系統功能這部分代碼則可以不必投入太大的精力去調試,因為這部分調試的工作在操作系統發布的時候就已經由微軟做好了。本文通過外殼編程,實現了搜尋文件、運行程序、控制工具條、最大最小化窗口的功能。
實現方法
前面所說的直接使用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");
……
謝謝
8. 簡單的shell編程
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#define BUFFERSIZE 80
extern char *get_current_dir_name(void);
extern char *getenv(const char *name);
extern pid_t waitpid(pid_t pid, int *status, int options);
char buffer[BUFFERSIZE+1];
main()
{
char *path, *arg[10], *input;
int li_inputlen, is_bj, is_back, i, j, k, pid, status;
char lc_char;
while (1){
/* initiations */
is_bj = 0; /*redirection flag*/
is_back = 0; /*background*/
/* shell prompt */
path = get_current_dir_name();
printf("%s>$",path);
/*開始獲取輸入*/
li_inputlen = 0;
lc_char = getchar();
while (lc_char !='\n'){
if(li_inputlen < BUFFERSIZE)
buffer[li_inputlen++] = lc_char;
lc_char = getchar();
}
/*命令超長處理*/
if (li_inputlen >= BUFFERSIZE){
printf("Your command is too long! Please re-enter your command!\n");
li_inputlen = 0; /*reset */
continue;
}
else
buffer[li_inputlen] = '\0';/*加上串結束符號,形成字串*/
/*將命令從緩存拷貝到input中*/
input = (char *) malloc(sizeof(char) * (li_inputlen+1));
strcpy(input,buffer);
/* 獲取命令和參數並保存在arg中*/
for (i = 0,j = 0,k = 0;i <= li_inputlen;i++){
/*管道和重定向單獨處理*/
if (input[i] == '<' || input[i] == '>' || input[i] =='|'){
if (input[i] == '|')
pipel(input,li_inputlen);
else
redirect(input,li_inputlen);
is_bj = 1;
break;
}
/*處理空格、TAB和結束符。不用處理『\n',大家如果仔細分析前面的獲取輸入的程序的話,
*不難發現回車符並沒有寫入buffer*/
if (input[i] == ' ' || input[i] =='\t' || input[i] == '\0'){
if (j == 0) /*這個條件可以略去連在一起的多個空格或者tab*/
continue;
else{
buffer[j++] = '\0';
arg[k] = (char *) malloc(sizeof(char)*j);
/*將指令或參數從緩存拷貝到arg中*/
strcpy(arg[k],buffer);
j = 0; /*准備取下一個參數*/
k++;
}
}
else{
/*如果字串最後是『&',則置後台運行標記為1*/
if (input[i] == '&' && input[i+1] == '\0'){
is_back = 1;
continue;
}
buffer[j++] = input[i];
}
}
free(input);/*釋放空間*/
/*如果輸入的指令是leave則退出while,即退出程序*/
if (strcmp(arg[0],"leave") == 0 ){
printf("bye-bye\n");
break;
}
/*如果輸入的指令是about則顯示作者信息,同時結束本條命令的解析過程*/
if (strcmp(arg[0]," about") == 0 ){
printf("right by shike,[email protected]\n");
continue;
}
if (is_bj == 0){ /*非管道、重定向指令*/
/*在使用xxec執行命令的時候,最後的參數必須是NULL指針,
*所以將最後一個參數置成空值*/
arg[k] = (char *) 0;
/*判斷指令arg[0]是否存在*/
if (is_fileexist(arg[0]) == -1 ){
printf("This command is not found?!\n");
for(i=0;i<k;i++)
free(arg[i]);
continue;
}
/* fork a sub-process to run the execution file */
if ((pid = fork()) ==0) /*子進程*/
execv(buffer,arg);
else /*父進程*/
if (is_back == 0) /*並非後台執行指令*/
waitpid(pid,&status,0);
/*釋放申請的空間*/
for (i=0;i<k;i++)
free(arg[i]);
}
}
}
int is_fileexist(char *comm)
{
char *path,*p;
int i;
i = 0;
/*使用getenv函數來獲取系統環境變數,用參數PATH表示獲取路徑*/
path = getenv("PATH");
p = path;
while (*p != '\0'){
/*路徑列表使用『:』來分隔路徑*/
if (*p != ':')
buffer[i++] = *p;
else{
buffer[i++] = '/';
buffer[i] = '\0';
/*將指令和路徑合成,形成pathname,並使用access函數來判斷該文件是否存在*/
strcat(buffer,comm);
if (access(buffer,F_OK) == 0) /*文件被找到*/
return 0;
else
/*繼續尋找其它路徑*/
i = 0;
}
p++;
}
/*搜索完所有路徑,依然沒有找到則返回-1*/
return -1;
}
int redirect(char *in,int len)
{
char *argv[30],*filename[2];
pid_t pid;
int i,j,k,fd_in,fd_out,is_in = -1,is_out = -1,num = 0;
int is_back = 0,status=0;
/*這里是重定向的命令解析過程,其中filename用於存放重定向文件,
*is_in, is_out分別是輸入重定向標記和輸出重定向標記*/
for (i = 0,j = 0,k = 0;i <= len;i++){
if (in[i]==' '||in[i]=='\t'||in[i]=='\0'||in[i] =='<'||in[i]=='>'){
if (in[i] == '>' || in[i] == '<'){
/*重定向指令最多'<','>'各出現一次,因此num最大為2,
*否則認為命令輸入錯誤*/
if (num < 3){
num ++;
if (in[i] == '<')
is_in = num - 1;
else
is_out = num - 1;
/*處理命令和重定向符號相連的情況,比如ls>a*/
if (j > 0 && num == 1) {
buffer[j++] = '\0';
argv[k] = (char *) malloc(sizeof(char)*j);
strcpy(argv[k],buffer);
k++;
j = 0;
}
}
else{
printf("The format is error!\n");
return -1;
}
}
if (j == 0)
continue;
else{
buffer[j++] = '\0';
/*尚未遇到重定向符號,字元串是命令或參數*/
if (num == 0){
argv[k] = (char *) malloc(sizeof(char)*j);
strcpy(argv[k],buffer);
k++;
}
/*是重定向後符號的字元串,是文件名*/
else{
filename[status] = (char *) malloc(sizeof(char)*j);
strcpy(filename[status++],buffer);
}
j = 0; /*initate*/
}
}
else{
if (in[i] == '&' && in[i+1] == '\0'){
is_back = 1;
continue;
}
buffer[j++] = in[i];
}
}
argv[k] = (char *) 0;
if (is_fileexist(argv[0]) == -1 ){
printf("This command is not founded!\n");
for(i=0;i<k;i++)
free(argv[i]);
return 0;
}
if ((pid = fork()) ==0){
/*存在輸出重定向*/
if (is_out != -1)
if((fd_out=open(filename[is_out],O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR))==-1){
printf("Open out %s Error\n",filename[is_out]);
return -1;
}
/*存在輸入重定向*/
if (is_in != -1)
if((fd_in=open(filename[is_in],O_RDONLY,S_IRUSR|S_IWUSR))==-1){
printf("Open in %s Error\n",filename[is_out]);
return -1;
}
if (is_out != -1)
/*使用p2函數將標准輸出重定向到fd_out上,p2(int oldfd,int newfd)實現的
*是把oldfd所指的文件描述符復制到newfd。若newfd為一已打開的文件描述詞,
*則newfd所指的文件會先被關閉,p2復制的文件描述詞與原來的文件描述詞
*共享各種文件狀態*/
if(p2(fd_out,STDOUT_FILENO)==-1){
printf("Redirect Standard Out Error\n");
exit(1);
}
if (is_in != -1)
if(p2(fd_in,STDIN_FILENO)==-1){
printf("Redirect Standard Out Error\n");
exit(1);
}
execv(buffer,argv);
}
else
if (is_back == 0) /*run on the TOP*/
waitpid(pid,&status,0);
for (i=0;i<k;i++)
free(argv[i]);
if (is_in != -1){
free(filename[is_in]);
close(fd_in);
}
if (is_out != -1){
free(filename[is_out]);
close(fd_out);
}
return 0;
}
int pipel(char *input,int len)
{
char *argv[2][30];
int i,j,k,count,is_back = 0;
int li_comm = 0,fd[2],fpip[2];
char lc_char,lc_end[1];
pid_t child1,child2;
/*管道的命令解析過程*/
for (i = 0,j = 0,k = 0;i <= len;i++){
if (input[i]== ' ' || input[i] == '\t' || input[i] == '\0' || input[i] == '|'){
if (input[i] == '|' ) /*管道符號*/
{
if (j > 0)
{
buffer[j++] = '\0';
/*因為管道連接的是兩個指令,所以用二維數組指針來存放命令和參數,
*li_comm是表示第幾個指令*/
argv[li_comm][k] = (char *) malloc(sizeof(char)*j);
strcpy(argv[li_comm][k++],buffer);
}
argv[li_comm][k++] = (char *) 0;
/*遇到管道符,第一個指令完畢,開始准備接受第二個指令*/
li_comm++;
count = k;
k=0;j=0;
}
if (j == 0)
continue;
else
{
buffer[j++] = '\0';
argv[li_comm][k] = (char *) malloc(sizeof(char)*j);
strcpy(argv[li_comm][k],buffer);
k++;
}
j = 0; /*initate*/
}
else{
if (input[i] == '&' && input[i+1] == '\0'){
is_back = 1;
continue;
}
buffer[j++] = input[i];
}
}
argv[li_comm][k++] = (char *) 0;
if (is_fileexist(argv[0][0]) == -1 ){
printf("This first command is not found!\n");
for(i=0;i<count;i++)
free(argv[0][i]);
return 0;
}
/*指令解析結束*/
/*建立管道*/
if (pipe(fd) == -1 ){
printf("open pipe error!\n");
return -1;
}
/*創建第一個子進程執行管道符前的指令,並將輸出寫到管道*/
if ((child1 = fork()) ==0){
/*關閉讀端*/
close(fd[0]);
if (fd[1] != STDOUT_FILENO){
/*將標准輸出重定向到管道的寫入端,這樣該子進程的輸出就寫入了管道*/
if (p2(fd[1],STDOUT_FILENO) == -1){
printf("Redirect Standard Out Error\n");
return -1;
}
/*關閉寫入端*/
close(fd[1]);
}
execv(buffer,argv[0]);
}
else{ /*父進程*/
/*先要等待寫入管道的進程結束*/
waitpid(child1,&li_comm,0);
/*然後我們必須寫入一個結束標記,告訴讀管道進程數據到這里就完了*/
lc_end[0] = 0x1a;
write(fd[1],lc_end,1);
close(fd[1]);
if (is_fileexist(argv[1][0]) == -1 ){
printf("This command is not founded!\n");
for(i=0;i<k;i++)
free(argv[1][i]);
return 0;
}
/*創建第二個進程執行管道符後的指令,並從管道讀輸入流 */
if ((child2 = fork()) == 0){
if (fd[0] != STDIN_FILENO){
/*將標准輸入重定向到管道讀入端*/
if(p2(fd[0],STDIN_FILENO) == -1){
printf("Redirect Standard In Error!\n");
return -1;
}
close(fd[0]);
}
execv(buffer,argv[1]);
}
else /*父進程*/
if (is_back == 0)
waitpid(child2,NULL,0);
}
for (i=0;i<count;i++)
free(argv[0][i]);
for (i=0;i<k;i++)
free(argv[1][i]);
return 0;
}
以前寫的,好像一些細節不一樣,不明白的地方,發郵件給我,[email protected]