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]