脚本学习

本文详细介绍了Shell脚本的使用,包括利用gcc编译C代码、自动生成脚本信息的快捷方式,以及一系列文本处理工具的用法,如grep、diff、patch、cut、sort、tr、sed和awk。通过实例展示了如何判断数字、检查文件属性、实现大小写不敏感输入以及查询交互式登录用户等实用脚本示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

脚本(Script)是批处理文件的延伸,是一种纯文本保存的程序,一般来说的计算机脚本程序是确定的一系列控制计算机进行运算操作动作的组合,在其中可以实现一定的逻辑分支等。

一、使用gcc在shell中编写C代码:

gcc的执行过程
使用gcc由C语言源代码文件生成可执行文件要经历四个相互关联的步骤∶预处理(也称预编译,Preprocessing)、编译(Compilation)、汇编(Assembly)和连接(Linking)。
命令gcc首先调用cpp进行预处理,在预处理过程中,对源代码文件中的文件包含(include)、预编译语句(如宏定义define等)进行分析。接着调用cc1进行编译,这个阶段根据输入文件生成以.o为后缀的目标文件。
汇编过程是针对汇编语言的步骤,调用as进行工作,一般来讲,.S为后缀的汇编语言源代码文件和汇编、.s为后缀的汇编语言文件经过预编译和汇编之后都生成以.o为后缀的目标文件。当所有的目标文件都生成之后,gcc就调用ld来完成最后的关键性工作,这个阶段就是连接。在连接阶段,所有的目标文件被安排在可执行程序中的恰当的位置,同时,该程序所调用到的库函数也从各自所在的档案库中连到合适的地方

[root@localhost ~]# yum install gcc -y
[root@41 mnt]# vim hello.c
#include<stdio.h>
main()
{
        printf("HELLO,GCC\n");
        return 0;
}

[root@41 mnt]# chmod +x hello.c
[root@41 mnt]# ./a.out    #默认生成文件
HELLO,GCC
[root@41 mnt]# gcc -Wall hello.c -o custom   #编译并链接生成custom文件
hello.c:2:1: warning: return type defaults to ‘int’ [-Wreturn-type]
 main()
[root@41 mnt]# ./custom 
HELLO,GCC
二、自动生成脚本信息
1.快捷键生成

在vim配置文件中追加:

[root@localhost ~]# vim /etc/vimrc 
map <F5> ms:call WESTOS()<cr>'s                   #将生成信息的命令映射到F5键
;autocmd BufNewFile *.sh exec ":call WESTOS()"    #实现新建.sh脚本文件时自动生成信息
func WESTOS ()
        call append(0,"###################################")
        call append(1,"#     Author:      Vincent".("        #"))
        call append(2,"#     Verion:             ".("        #"))
        call append(3,"#     Mail:   820027814@qq.com ".("   #"))
        call append(4,"#     Date:               ".("        #"))
        call append(5,"#     Description:        ".("        #"))
        call append(6,"#                         ".("        #"))
        call append(7,"###################################")
        call append(8," ")
        call append(9,"#!/bin/bash")
endfunc

在文本中按快捷键F5后,文本之前自动生成以下信息:

[root@localhost mnt]# vim file.sh
###################################
#     Author:      Vincent        #
#     Verion:                     #
#     Mail:   820027814@qq.com    #
#     Date:                       #
#     Description:                #
#                                 #
###################################

#!/bin/bash
2.新建脚本中自动生成

将map行为该行

                           autocmd BufNewFile *.sh exec ":call WESTOS()"  
三、文本处理工具

1.grep-print lines matching a pattern

grep searches the named input FILEs (or standard input if no files are named, or if a single hyphen-minus (-) is given as file name) for lines containing a match to the given PATTERN. By default, grep prints the matching lines.

   -i, --ignore-case
   -n, --line-number
          Prefix each line of output with the 1-based line  number  within
          its input file.
   -r, --recursive
          Read all files  under  each  directory,  recursively,  following
          symbolic  links  only  if they are on the command line.  This is
          equivalent to the -d recurse option.
   -c, --count
          Suppress  normal output; instead print a count of matching lines
          for each input file.  With the -v,  --invert-match  option  (see
          below), count non-matching lines
    -E, --extended-regexp
          Interpret PATTERN as an extended regular  expression  (ERE,  see
          below).  (-E is specified by POSIX.)
    -v, --invert-match
          Invert the sense of matching, to select non-matching lines.  (-v
          is specified by POSIX.)

过滤查找vincent所在行

[root@141 grep]# grep vincent /etc/passwd
vincent:x:1001:1001::/home/vincent:/bin/bash

查找vincent开头的行

[root@141 grep]# grep ^vincent /etc/passwd
vincent:x:1001:1001::/home/vincent:/bin/bash

查找以/bin/bash结尾行

[root@141 mnt]# grep /bin/bash$ passwd 
root:x:0:0:root:/root:/bin/bash
student:x:1000:1000:Student User:/home/student:/bin/bash

忽略大小写查找

[root@141 mnt]# grep -i ROOt passwd 
root:x:0:0:root:/root:/bin/bash

反向查找(过滤)

[root@141 mnt]# grep -i -v ROOt passwd 
jzx:x:1002:1005::/home/jzx:/bin/bash
smb1:x:1003:1006::/home/smb1:/sbin/nologin

查找并显示行号

[root@141 grep]# grep -n vincent /etc/passwd
40:vincent:x:1001:1001::/home/vincent:/bin/bash

递归查找目录下所有文件

[root@141 grep]# grep -r vincent /etc
/etc/group:vincent:x:1001:
/etc/gshadow:vincent:!::

仅计算查找字符重复的行数

[root@141 grep]# grep -c vincent /etc/passwd
1

显示除含有vincent字符的行

[root@141 grep]# grep -v vincent /etc/passwd

2.diff - compare files line by line

compare files line by line

DESCRIPTION
       -u, -U NUM, --unified[=NUM]
          output NUM (default 3) lines of unified context

-a或–text  diff预设只会逐行比较文本文件。
-N或–new-file  在比较目录时,若文件A仅出现在某个目录中,预设会显示:Only in目录:文件A若使用-N参数,则diff会将文件A与一个空白的文件比较。
-u,-U或–unified=  以合并的方式来显示文件内容的不同。
-r或–recursive  比较子目录中的文件。

[root@localhost ~]# echo "vincent" > westos1
[root@localhost ~]# echo "westos" > westos
[root@localhost ~]# diff -u westos westos1
--- westos  2018-06-09 23:04:11.932300926 -0400
+++ westos1 2018-06-09 23:03:19.180300926 -0400
@@ -1 +1 @@
-westos
+vincent

保存文件的不同到another.path

[root@localhost ~]# diff -u westos1 westos > another.path

3.patch-apply changes to files

apply changes to files

首先要安装patch包

[root@localhost ~]# yum install patch -y

把westos1转为westos文件,而another.path保存了两个文件的区别

[root@localhost ~]# patch westos1 another.path 
[root@localhost ~]# cat westos1
linux 
[root@localhost ~]# cat westos
linux 
[root@localhost ~]# cat another.path 
--- westos1 2018-06-09 22:44:45.167300926 -0400
+++ westos  2018-06-09 22:57:01.535300926 -0400
@@ -1 +1 @@
-westos1
+linux 

4. cut - remove sections from each line of files

Print selected parts of lines from each FILE to standard output.

   -d, --delimiter=DELIM
          use DELIM instead of TAB for field delimiter
   -f, --fields=LIST
          select only these fields;  also print any line that contains  no
          delimiter character, unless the -s option is specified
   -b, --bytes=LIST
          select only these bytes

   -c, --characters=LIST
          select only these characters

查看passwd文件初始内容

[root@141 grep]# cat passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin

截取字符

[root@141 grep]# cut -d : -f 1,3 passwd 
root:0
bin:1
daemon:2
adm:3
# 表示指定分隔文件的符号为":" “-f 1,3 ”表示截取以 :分隔后的第一段和第三段。

awk命令:对于内容为以下的文件: 1 2 3 4 如果想把2截出来,执行这个命令是不行的。 cut -d ” ” -f 3 file 截出的内容是空格。
这个时候就只能用awk命令了。 awk -F ” ” ‘{print $3}’ file 它可以忽略空格的个数而把2截出来。

[root@141 grep]# echo "1     2     3" > testfile
[root@141 grep]# awk -F " " '{print $3}' testfile 
3

截取IP示例:

[root@141 grep]# ifconfig eth0|grep "inet "|awk -F " " '{print $2}' 
172.254.25.141

或者

[root@141 grep]# ifconfig eth0|grep inet|grep inet6 -v|awk -F " " '{print $2}'
172.254.25.141

5.sort - sort lines of text files

Write sorted concatenation of all FILE(s) to standard output.

   -n, --numeric-sort
          compare according to string numerical value
   -r, --reverse
          reverse the result of comparisons

file为一个纯数字文件,对于含有汉字和数字的文件,汉字默认会被排到数字前面

实验:

[root@141 grep]# sort sort_file    #仅以第一位从小到大排列
1
44
5 
[root@141 grep]# sort -n sort_file   #:从小到大排列
1
2
2
3
[root@141 grep]# sort -nr sort_file    #从大到小排列
65
44
1
[root@141 grep]# sort -nu sort_file  #从小到大排列并剔除重复的部分
1
2
3

uniq

uniq - report or omit repeated lines

   -c, --count
          prefix lines by the number of occurrences
   -d, --repeated
          only print duplicate lines, one for each group
   -u, --unique
          only print unique lines

       sort -n file |uniq -d    与-u相反,它会把
       sort -n file |uniq -c   即如果有两个二 会显示 2 2

不会显示重复的行

[root@141 grep]# sort -n sort_file | uniq -u
1
3
[root@141 grep]# sort -n sort_file | uniq -d   #显示所有的重复行
2
[root@141 grep]# sort -n sort_file | uniq -c   # 标准输出,左边是数字个数,右边是不重复的数字排列。
      1 1
      2 2
      1 3
      1 5 
6.tr- translate or delete characters

Translate, squeeze, and/or delete characters from standard input, writing to standard output.

[root@141 grep]# echo VINCent > tr_file
[root@141 grep]# tr 'a-z' 'A-Z' < tr_file  #文件内容全部转换成大写输出。
VINCENT
[root@141 grep]# tr 'A-Z' 'a-z' < tr_file #文件内容全部转换成小写输出。
vincent
7.sed - stream editor for filtering and transforming text

Sed is a stream editor. A stream editor is used to perform basic text transformations on an input stream (a file or input from a pipeline). While in some ways similar to an editor which permits scripted edits (such as ed), sed works by making only one pass over the input(s), and is consequently more efficient. But it is sed’s ability to filter text in a pipeline which particularly distinguishes it from other types of editors.

     -n, --quiet, --silent
          suppress automatic printing of pattern space
      -e script, --expression=script
          add the script to the commands to be executed

显示UUID和/dev开头行

[root@141 mnt]# sed -ne '/^UUID/p;/\/dev/p' fstab  #\代表转义
# Accessible filesystems, by reference, are maintained under '/dev/disk'
UUID=9bf6b9f7-92ad-441b-848e-0257cbb883d1 /                       xfs     defaults        1 1
/dev/vg0/vo /home   ext4    defaults    0 0

在内容后添加字符

[root@141 mnt]# sed -e '/23/avincent' sed_test 
12
23
vincent
34

/d 不显示

[root@141 mnt]# sed -e '/12/d;/23/d' sed_test 
34

/c 替换

[root@141 mnt]# sed -e '/12/cjzx' sed_test 
jzx
23
34

/i 插入

[root@141 mnt]# sed -e '/23/ijzx' sed_test 
12
jzx
23
34
[root@localhost mnt]# sed '/^UUID/w file' fstab     #保存UUID所在行到文件并显示
[root@localhost mnt]# sed -n '/^UUID/w file' fstab  #保存到文件不显示
[root@localhost mnt]# sed '/^UUID/= ' fstab         #显示行数,结果和内容
[root@localhost mnt]# sed -n -e '/^UUIP/p' -e '/^UUID/= ' fstab #显示行数,只显示结果
9
[root@localhost mnt]# sed 'G' fstab                 #每行后加空行
[root@localhost mnt]# sed '$!G' fstab                     #每行后加空行,不包括最后一行
[root@localhost mnt]# sed 's/nologin/linux/g' passwd      #替换
[root@localhost mnt]# sed -e '/adm/,/sync/s/nologin/linux/g' passwd 
[root@localhost mnt]# sed 's/nologin/linux/g' -i  passwd  #替换并保存

8.awk

[root@141 mnt]# ifconfig eth0 | awk -F " " '/inet\>/{print $2}'      #过滤显示ip
172.254.25.141
[root@141 mnt]# awk -F : 'BEGIN{N=0}{N++}END{print N}' /etc/passwd  #显示passwd总行号
46

脚本示例:
脚本1:判断数字为小于10的整数
[root@localhost mnt]# vim check_number.sh
#!/bin/bash
[ -z "$1" ]&&{
        echo A number should be provided
        exit
}
[ "$1" -lt "0" ]&&{
        echo $1 is illegal
        exit
}
[ "$1" -ge "0" -a "$1" -lt "10" ]&&{
        echo $1 is less than 10
}||{
        echo $1 is great than 10
}

检验;

[root@localhost mnt]# sh check_number.sh 11
11 is great than 10
[root@localhost mnt]# sh check_number.sh 4
4 is less than 10
[root@localhost mnt]# sh check_number.sh -1
-1 is illegal
脚本2:校验文件属性
test- check file types and compare values
   -e FILE
          FILE exists
   -f FILE
          FILE exists and is a regular file
   -L FILE
          FILE exists and is a symbolic link (same as -h)
   -S FILE
          FILE exists and is a socket
   -b FILE
          FILE exists and is block special
   -d FILE
          FILE exists and is a directory
   -c FILE
          FILE exists and is character special
   FILE1 -ef FILE2
          FILE1 and FILE2 have the same device and inode numbers

   FILE1 -nt FILE2
          FILE1 is newer (modification date) than FILE2

   FILE1 -ot FILE2
          FILE1 is older than FILE2

检验文件是否存在

[root@localhost mnt]# [ -e  "vincent" ]&&echo yes||echo no
yes
[root@localhost mnt]# [ -e  "vinnt" ]&&echo yes||echo no
no
脚本:检验并输出某文件的属性
[root@localhost mnt]# vim file_update.sh 
#!/bin/bash
[ -z "$1" ]&&{
        echo enter a path
        exit 1
}
[ -e "$1" ]&&{
        echo FILE exists
}||[ -f "$1" ]&&{
        echo FILE exists and is a regular file
}||[ -L "$1" ]&&{
        echo  FILE exists and is a symbolic link 
}||[ -S "$1" ]&&{
        echo FILE exists and is a socket
}||[ -b "$1" ]&&{
        echo FILE exists and is block special
}||[ -d "$1" ]&&{
        echo FILE exists and is a directory
}||[ -c "$1" ]&&{
        echo FILE exists and is character special
}

检验:

[root@localhost mnt]# sh check_file.sh /mnt/file
FILE exists
FILE exists and is a directory
脚本3:实现可大小写输入
[root@localhost mnt]# vim tr.sh
#!/bin/bash
WORD=$(echo $1 | tr 'A-Z' 'a-z')
[ "$WORD" = "hello" ]&&{
        echo yes
}||{
        echo no
}

检验;

[root@localhost mnt]# sh tr.sh HELLO
yes
[root@localhost mnt]# sh tr.sh mk
no
[root@localhost mnt]# sh tr.sh hello
yes
脚本4:查询可交互式登录用户

首先查看shells中哪些可以登录,把nologin过滤掉,其余作为搜索项在/etc/passwd中查找用户

[root@141 mnt]# cat /etc/shells 
/bin/sh
/bin/bash
/sbin/nologin
/usr/bin/sh
/usr/bin/bash
/usr/sbin/nologin
/bin/tcsh
/bin/csh
[root@141 mnt]# vim test.sh
#!/bin/bash
SHELL=$(echo `grep -v nologin /etc/shells`| sed 's/ /|/g')
grep -E $SHELL /etc/passwd | cut -d : -

检验:

[root@141 mnt]# sh test.sh 
root
student
vincent

相当于命令:
grep -e "echo `grep -v nologin /etc/shells` | sed 's/ /|/g'" /etc/passwd | cut -d : -f 1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值