Linux

Starter

特点

  • 优点:
    • 免费,开源
    • 支持多线程,多用户
    • 安全性好
    • 对内存和文件管理优越
    • linux 最小只需 4M => 嵌入式开发
  • 缺点:
    • 操作相对困难

历史

  1. 1960 麻省理工学院 30 个人同时使用
  2. 1965 mit,ge,bell 30 =>300 个人分时操作,multis计划【火星计划】
  3. 1969 火星计划失败,ken开发了一个file server system【文件系统】
  4. 1973 unix诞生 开源
    • IBM: aix
    • Sun: solaris
    • Hp: hp-Unix
    • 伯克利分校: bsd
  5. minix系统
  6. linus 芬兰 PC386 => 将minix移植到PC,1991=> 1994(1.0) linux[linus is not unix]
  7. RedHat红帽子公司
    • s.u.s.e
    • 红旗linux
    • Ubuntu

运行级别

  • 运行级别:
    • 0 关机
    • 1 单用户
    • 2 多用户,无网络服务
    • 3 多用户,有网络服务
    • 4 系统未使用,保留给用户
    • 5 图形界面
    • 6 系统重启
  • 常用运行级别 3/5
  • init[0123456] 启动
  • 修改运行级别 /etc/inittab => id:5:initdefault 修改这行中的数字
  • 解决错误配置后无法启动:
    • 在进入grub引导程序时,按e
    • 选择第二行,输入e
    • 在最后输入 1 回车,代表单用户级别( 因为单用户模式不读取 /etc/inittab文件 )
    • 按 b ,重新启动进入了单用户模式,再修改该配置文件

分区

  • 基本分区(Primary Partion)
    • 可以马上使用,单不能在分区
  • 扩展分区(Extension Partion)
    • 需进行二次分区后才可使用
    • 即逻辑分区(Logical Partion),且无数量限制
  • 硬盘
    • 一块硬盘上: 基本分区(主分区)+扩展分区个数<=4
    • 硬盘分两种:IDE/SCSI ("sdx~" / "hdx~")
      • sd :SCSI硬盘(较好)
      • hd :IDE硬盘
      • x :盘号 (a 基本盘,b基本从属盘,c铺助盘,d铺助从属盘 )
      • ~ :分区 ( 1-4 主分区或扩展盘 ,5 开始为逻辑分区 )
  • 相关命令:
    • mount [-参数] [设备名称] [挂载点]
    • umount [设备名称]
    • df 【查看磁盘使用情况】
    • df -l 【查看某个目录在哪个分区】
    • df -h
    • fdisk -l 【查看linux系统分区具体情况】

文件系统

级层式的树状目录结构,根目录 /

  • root 【存放root用户的相关文件】
  • home 【存放普通用户的相关文件】
  • bin 【存放常用命令】
  • sbin 【存放需具有一定权限才可使用的命令】
  • mnt 【默认挂载软驱,光驱的目录】
  • etc 【存放系统配置与管理的相关文件】
  • var 【存放经常变化的文件,具有变动性质的相关程序目录】
  • boot 【存放系统启动时的引导文件】
  • usr 【程序默认安装处】
  • dev 【接口设备文件目录,如had表示硬盘】
  • proc 【目前系统核心与程序执行的信息】
> ls -l
-rw-r--r--| 1 | tom | policeman  |    11 |  Dec 9 09:32   | myTest.java
  • -|rw-|r--|r-- 文件类型及权限
    • 文件类型
      • -代表普通文件
      • d代表文件夹 (其实也是个文件)
      • l代表链接
    • 文件的所有者对该文件的权限
    • 文件所在组的其他用户对该文件的权限
    • 其他组的用户对该文件的权限
  • 1
    • 若myTest.java是个文件,则为 1
    • 若myTest.java是个文件夹,则表示次文件夹下有多少个文件
  • tom 文件所有者
  • policeman 文件所在组
  • 11 文件大小
  • Dec 9 09:32 最后修改日期
  • myTest.java 文件名

文件使用:

    • groupadd policeman 【添加组】
    • cat /etc/group | more 【查看所有linux中所有组信息】
    • eg:policeman:x:503
      • x :密码(加密了)
      • 503 :代表policeman这个组的id
  1. 用户

    • useradd -g 组名 用户名 【创建用户,并将该用户分配到指定组中】
    • passwd xxxxx 【设置密码】
    • usermod -g 组名 用户名 【改变某个用户所在组(root才可操作)】
    • userdel 用户名 【删除用户】
    • userdel -r tom 【删除用户以及该用户主目录】
    • eg:

      > useradd -g policeman tom`
      > cat /ect/password | more
      
      tom:x:503:503::/home/tom:/bin/bash
      (用户名):(密码):(用户ID):(用户所在组ID)::(用户主目录):(此用户使用的Shell解析器)
      
  2. 文件owner

    • chown 用户名 文件名【修改文件的所有者】
    • chgrp 组名 文件名 【修改文件的所在组】 +ls -ahl 【查看文件的所有者】
    • who am i【查看当前用户】
    • eg:
      > chown wang myTest.java
      > chown root ./tom
      > chown -R root ./tom    【改变tom这个目录及其下所有文件和目录的所有者为root】
      
  3. 文件访问权限(只有 root 和此文件的所有者可修改)

    • 权限分三组:
      • 文件所有者(o)
      • 同组用户(g)
      • 其余用户(a)
    • 每组权限分为3位:
      • r(read) 可读,用 4 表示
      • w(write) 可写,用 2 表示
      • x(execute) 可执行,用 1 表示
    • 权限是相加的,例如:
      • rwx是7
      • rw是6
    • 当对文件进行访问时,内核就检查进程关联的ID和该ID对应的权限位是否符合要求
    • 操作与权限
      操作 需要的权限
      创建/删除/改名 文件 对父目录的w和x权限,以及所有祖先目录的x权限
      修改文件权限 有效用户ID是文件所有者,或者拥有root权限
      修改文件内容 对父目录的x权限,以及所有祖先目录的x权限
      列出目录的文件列表 对父目录的rx权限,以及所有祖先目录的x权限
      修改文件的所有者 拥有root权限
    • 对于目录文件(文件夹)
      • 读取权限:列出文件夹里文件列表的权限
      • 写入权限:修改文件夹里的文件的名字的权限
      • 执行权限:进入文件夹的权限
    • eg:
      > chmod 777 tom
      > chmod 770 tom
      > chmod u=rwx,g=rx,o=rx tom
      > chmod u-x,g+w tom
      > chmod a+r tom
      
    • 注意:修改某文件夹的权限,不代表该文件夹下的文件的权限也跟着修改
  4. 文件三个主要的变动时间:

    • modification time (mtime):
      • 当该文件的『内容数据』变更时,就会升级这个时间
      • 内容数据指的是文件的内容,而不是文件的属性或权限
    • status time (ctime):
      • 当该文件的『状态 (status)』改变时,就会升级这个时间
      • 举例来说,像是权限与属性被更改了,都会升级这个时间
    • access time (atime):
      • 当『该文件的内容被取用』时,就会升级这个读取时间 (access)
      • 举例来说,我们使用 cat 去读取 /etc/man.config,就会升级该文件的 atime
    • 示例:
      > ls -l /etc/man.config
      -rw-r--r-- 1 root root 4617 Jan  6  2007 /etc/man.config
      > ls -l --time=atime /etc/man.config
      -rw-r--r-- 1 root root 4617 Sep 25 17:54 /etc/man.config
      > ls -l --time=ctime /etc/man.config
      -rw-r--r-- 1 root root 4617 Sep  4 18:03 /etc/man.config
      
  5. 修改文件时间或建置新档: touch

  6. 共享

    • windows <=> windows 使用网络邻居实现文件共享
    • windows <=> linux 使用samba服务

管道

  • stdin(fd=0) 标准输入 (文件描述符为0)
  • stdout(fd=1) 标准输出(文件描述符为1)
  • stderr(fd=2) 标准错误输出 (文件描述符为2)
  • > 将stdout定向输出到文件
    • 如果文件不存在,就创建文件;
    • 如果文件存在,就将其清空;
    • 相当于 1>,不包括stderr
    • >& 将stdout与stderr一起导向
    • (command > stdout_file) > &stderr_file 把stderr和stdout分开导向
      2 > file.txt    # 将文件句柄2(即stderr)重定向到文件file.txt中
      2 > &1          # 将文件句柄2(即stderr)重定向到文件句柄1(即stdout)指向的文件中
      test.sh > /tmp/test.log 2>&1
      
  • >> 将stdout追加到目标文件中
    • 如果文件不存在,就创建文件;
    • 如果文件存在,则将新的内容追加到那个文件的末尾
  • | 管道,连结上个指令的标准输出,做为下个指令的标准输入
    • cmd1 | cmd2 将cmd1 的 stdout 作为 cmd2 的 stdin
    • cmd1 | & cmd2 stderr合并到stdout, 然后管道到下一条命令

环境变量

# 查看环境变量
> env

# 查看某个环境变量
> echo 变量名

# 设置一个新变量
> export 变量名=变量值

# 在原变量值得基础上更新
> export 变量名=$变量名:xxx

# 清除某环境变量
> unset 变量名

例如:

export TEST="test"      # 增加一个变量
env|grep TEST           # 输出结果:   TEST=test
unset TEST              # 删除
env|grepTEST            # 没有输出,证明变量TEST已不存在
  • /etc/profile 全局的环境变量文件,只要登陆系统的用户都会执行里面的ENV环境变量设置
  • ~/.profile 用户环境变量
    • 在用户主目录下
    • 用户登陆时会执行此文件里的ENV环境变量设置
    • 执行. ~/.profile立即生效
  • ~/.kshrc~/.bshrc,~/.cshrc shell环境变量
    • 在用户主目录下
    • 执行对应Shell下面的子shell时会执行此文件里的ENV环境变量设置
    • 执行. ~/.kshrc/~/.bshrc/~/.cshrc立即生效
  • 注意
    • root用户的环境变量在/etc/profile
    • 从普通用户su到root时,环境变量设置可能不生效,需su - root
    • 处理直接执行配置文件外,也可使用source命令使配置生效

vi 编辑器

  1. vi Hello.java
  2. i 【进入到插入模式insert】
  3. esc键 【命令模式切换】
  4. 输入冒号
  5. wq 【保存退出】; q! 【退出不保存】

说明:

  • w 【写入保存】
  • q 【退出,若内容修改,vi会报错】
  • q! 【强制离开vi,并不保存文件】
  • wq 【保存并退出vi】
  • set nu 【在文件每行行处加入行号】
  • set nonu 【取消行号】
  • 输入数字,再按esc键 【将光标移至该行行首】
  • /字符串 【查找字符串,按n键往下继续查找】
  • ?字符串 【查找字符串,按n键往上继续查找】

Shell

Shell名称 开发者 命令名称
Bourne S.R.Bourne /bin/bash
C Bill Joy /bin/csh
Kom David /bin/ksh
  • env 【显示当前操作系统的环境变量】
  • chsh -s 新的shell 【修改当前使用的shell】
    • eg: chsh -s /bin/csh (生效需注销重新登录下)
  • 修改User的默认shell,有两种方式:
    • 直接修改 /etc/passwd 文件(eg: /sbin/sh => /bin/bsh
    • usermod -s /usr/bin/bash root
  • shell 解释为内核可执行的代码
    • 命令(eg:cp,mkdir) <=> Shell <=>linux内核

常用命令

shutdown -h now     立即进行关机
shutdown -r now     现在重新启动计算机
reboot            现在重新启动计算机
startx             进入图形界面

su -         切换用户
logout    用户注销
tab 快捷键,自动补全

man         【相当于help】
dir
ls -a         【显示隐藏文件】
ls -l         【显示长列表格式】
cd          【改变目录】
pwd       【显示当前工作目录】
mkdir     【建立目录】
rmdir     【删除空目录】
touch     【建立空文件】
more         【分页显示,上一页ctrl+pageUp】

cp              【复制命令】    
cp -r dir1 dir2     【递归复制命令】    eg:  cp a.out /home/tom/

mv
rm 
rm -rf             【删除所有内容,r表示递归,f表示强制】

ln                 【建立符合连接】
ln -s 源目标
ln -s /etc/inittab inittab 【inittab 指向实际文件 /etc/inittab】

find 目录 -name aaa.java
find 目录 -amin -10 【 10分钟内存取的文件或目录 atime小时】
find 目录 -cmin -10 【 10分钟内更改的文件或目录 ctime小时 +表示前】
find 目录 -size +10k【 大小为10k的文件 】

shell history 查阅历史记录命令
history 5 【 显示最近使用的5个命令 】
!5          【 执行历史编号为5的命令 】
!ls          【 执行最后一次以ls开头的命令 】
> uname
SunOS

> uname -n
SZ1SA006

> hostname
SZ1SA006

> logname
cim1tdtp

> echo $LOGNAME
cim1tdtp

> whoami     # 显示有效的当前用户
cim1tdtp

ls mv rm

  1. ls列出文件 / 文件夾 ls

     # 列出文件夾個數
     ls -l | grep ^d | wc -l
    
     # 列出非文件夾個數
     ls -l | grep -v ^d | wc -l
    
     # ls -F: 把文件按照类型归类(会在末尾加上/ *等符号标识)
     # grep /$ 挑出以/结尾的行 ;PS:/标识是目录
     ls -F | grep /$
    
  2. mv 移动/重命名

     mv MCK9[1-3]* 2009\.
     cat temp.txt | xargs -n1 -i mv {} 2011/
    
  3. rm 刪除文件或目錄

     rm [-dfirv][--help][--version][文件或目录...]
    
  4. -d,--directory 删除目录。
  5. -f,--force 强制删除文件或目录(即使原档案属性设为唯读,也直接删除,无需逐一确认)
  6. -i--interactive 删除前逐一询问确认。
  7. -r,-R,--recursive 递归处理,将指定目录下的所有文件及子目录一并处理。
  8. -v,--verbose 显示指令执行过程。
  9. --help 在线帮助。
  10. --version 显示版本信息
  11. 注意:删除目录必须加上参数-r,否则预设仅会删除文件

      #刪除文件
      rm file
    
      #删除所有C语言程式档;删除前逐一询问确认
      rm -i *.c
    
      #刪除文件夾
      rm -r dir
    
      #批量刪除符合條件的文件
      ls -d * | grep -v tar | xargs -n5 rm -r
    

tar,gzip,zip

ls -d * | xargs -n5 -i tar -cf {}.tar {}
ls -d * | xargs -n5 -i zip -r "{}.zip" {}
  1. tar

    • 参数:
      • -c 创建一个新归档
      • -x 从归档中抽取文件
      • -f
        • -c 选项一起使用时,创建的 tar 文件使用该选项指定的文件名;
        • -x选项一起使用时,则解除该选项指定的归档
      • -t 显示包括在 tar 文件中的文件列表
      • -v 显示文件的归档进度
      • -z 使用 gzip 来压缩 tar 文件
      • -j 使用 bzip2 来压缩 tar 文件
    • 包 (.tar文件)
      • 打包: tar cvf FileName.tar DirName
      • 解包: tar xvf FileName.tar
      • 注:tar是打包,不是压缩!
    • 压缩包 (.tar.Z)
      • 解压:tar Zxvf FileName.tar.Z
      • 压缩:tar Zcvf FileName.tar.Z DirName
    • 示例:

      # 将test文件夹打包为test.tar
      tar cvf test.tar test                #將test文件夾打包為test.tar
      # 将test.tar包进行压缩为test.tar.Z文件
      compress test.tar
      
      # 解压FileName.Z文件
      uncompress FileName.Z
      
      # 一步到位,直接解压解包
      uncompress < test.tar.Z | tar xf
      
  2. gzip

    • 参数:
      • -c 将输出写到标准输出上,并保留原有文件。
      • -d 将压缩文件解压。
      • -l 对每个压缩文件,显示下列字段:
      • -r 递归式地查找指定目录并压缩其中的所有文件或者是解压缩。
      • -t 测试,检查压缩文件是否完整。
      • -v 对每一个压缩和解压的文件,显示文件名和压缩比。
      • -num 用指定的数字num调整压缩的速度
        • -1--fast表示最快压缩方法(低压缩比)
        • -9--best表示最慢压缩方法(高压缩比)
        • 系统缺省值为6
    • 示例:

      # 压缩
      gzip FileName
      
      # 解压缩
      gzip -dv FileName
      
  3. zip/unzip

    zip [参数] [打包后的文件名] [打包的目录路径]
    
  4. 参数:
    • -a 将文件转成ASCII模式
    • -F 尝试修复损坏的压缩文件
    • -h 显示帮助界面
    • -m 将文件压缩之后,删除源文件
    • -n 特定字符串 不压缩具有特定字尾字符串的文件
    • -o 将压缩文件内的所有文件的最新变动时间设为压缩时候的时间
    • -q 安静模式,在压缩的时候不显示指令的执行过程
    • -r 将指定的目录下的所有子目录以及文件一起处理
    • -S 包含系统文件和隐含文件(S是大写)
  5. 示例

      #压缩文件夹
      zip -r test.zip test
    
      #解压
      unzip test.zip
    
  6. 更多参考

ps,kill

查杀进程

ps -ef | grep nationz | grep "sh -c" | awk '{print $2}' | xargs -i kill -9 {}
ps -e -o pid -o comm
ps -ax -o pid -o comm | grep oic
ps -ax -o pid -o comm | grep oic
ps -e -o pid -o comm | grep oic | awk '{print $1}' | xargs -n2 -i kill -9 {}
kill -9 `ps -a -o pid -o comm | grep oic | awk '{print $1}'`

jobs,fg,bg

> sleep 15 &
[1] 2706

#列出当前活动作业
> jobs
[1]  + Running              sleep 15

# 显示作业号,PID
# jobs -l
[1]  +  2706 Running              sleep 15

> jobs
[1]    Done                 sleep 15

> sleep 15            #按^Z停止sleep命令(sleep没有使用CPU但被挂起在后台)
^Z
Stopped (user)

> bg                #使最后一个后台作业在后台开始执行
[1]  + sleep 15 &
> jobs
[1]  + Running              sleep 15

> fg %1            #将编号为[1]的作业拿到前台
sleep 15

du,mount

  1. du 查看文件或者目录大小

    • -a:显示全部目录和其次目录下的每个档案所占的磁盘空间
    • -b:大小用bytes来表示 (默认值为k bytes)
    • -c:最后再加上总计 (默认值)
    • -s:只显示各档案大小的总合 (summarize)
    • -x:只计算同属同一个档案系统的档案
    • -L:计算所有的档案大小
    • 常用:du -smdu -sh. 查询档案或目录的磁盘使用空间
    • fdisk: 查看硬件分区的大小的
      • 一般使用:fdisk -l
      • 如果挂载了多块硬盘,每个硬盘有多个分区,就是用fdisk
    • eg:
      du -a
      du -h | awk '$1 ~ /G/'
      du -h | awk '$1 ~ /M/'
      du -ks /tmp
      df -k
      
  2. 装载 mount

     # 装载
     mount [-t vfstype] [-o options] device dir
    
     # 卸载
     umount dir
    
  3. -a/etc/fstab 中定义的所有档案系统挂上

  4. -f伪装mount,作出检查设备和目录的样子,但并不真正挂载文件系统。
  5. -n 不把安装记录在/etc/mtab 文件中。
  6. -r 讲文件系统安装为只读。
  7. -v 详细显示安装信息。
  8. -w 将文件系统安装为可写,为命令默认情况。
  9. -t 指定设备的文件系统类型
    • ext2 linux目前常用的文件系统
    • msdos MS-DOS的fat,就是fat16
    • vfat windows98常用的fat32
    • nfs 网络文件系统
    • iso9660 CD-ROM光盘标准文件系统
    • ntfs windows NT/2000/XP的文件系统
    • auto 自动检测文件系统
  10. -o 指定挂载文件系统时的选项,有些也可写到在/etc/fstab中

    • defaults 使用所有选项的默认值(auto、nouser、rw、suid)
    • auto/noauto 允许/不允许以 –a选项进行安装
    • dev/nodev 对/不对文件系统上的特殊设备进行解释
    • exec/noexec 允许/不允许执行二进制代码
    • suid/nosuid 确认/不确认suid和sgid位
    • user /nouser 允许/不允许一般用户挂载
    • codepage=XXX 代码页
    • iocharset=XXX 字符集
    • ro 以只读方式挂载
    • rw 以读写方式挂载
    • remount 重新安装已经安装了的文件系统
  11. 例如:

      mount 10.7.33.25:/cim1_release /cim
      umount /cim
    
  12. 注意:

    • 挂载点(dir):必须是一个已经存在的目录(目录可以不为空,但挂载后原内容将不可用,umount后恢复正常)
    • 开机重启后自动挂载,需将挂载设置在/etc/vfstab文件中
      • 例如:将10.7.33.25:/cim1_release/ - /cim nfs - yes bg,soft添加到文件中
  13. 更多参考

重执行命令

  • ! 执行来自历史清单的一个命令

    • !^ 取得第1个变元
    • !$ 取得最后一个变元
    • !* 取得所有变元
    • !:2 取得第2个变元

      cat file1 file2 file3
      ( 0     1        2     3   )
      
      ls !:2    # ls file2
      ls !^    # ls file1
      ls !$    # ls file3
      ls !*    # ls file1 file2 file3
      !!:p        # ls file1 file2 file3     (打印但不执行历史清单中的最后一个命令,更新历史清单)
      
      # 从历史清单中取得最后一个命令重新执行
      !!
      
      # 重新执行历史清单中的第三个命令
      !3
      
      # 重新执行历史清单中以d开头的最后一个命令
      !d
      
  • ^ 编辑前一个命令的一种快捷方法
    # 替换历史清单中最后一个命令中的字母
    # 用一个t取得第一次出现的r
    ^r^t
    

cut

cut -b|c|f list [-d delim][-s][file ...]

从指定的范围中提取信息

  • 提取形式:

    • -b 表示字节,即byte
    • -c 表示字符,即character
    • -f 表示字段,即field
  • 提取范围(具体数字,从1开始计数):

    • m 第m个字节或字符或字段
    • m- 从第m个字节或字符或字段到文件结束
    • m-n 从第m个到第n个字节或字符或字段
    • -n 从第1个到第n个字节或字符或字段
  • 提取设置:

    • -d 用来定义分隔符(delimiter),默认为tab键
    • -s 表示不包括哪些不含分隔符的行(有利于去掉注释和标题)

示例:

cut -c 1-5,10-14 test
cut -f 1,3 test
cut -d'|' -f2  1.test > 2.test
cut -d':' -f1,2  1.test > 2.test 
cut -d':' -f1-4 /etc/passwd | head -10
cut -d':' -f 1-4 /etc/passwd | head -10

find

find  path  -option  [  -print ]  [ -exec|-ok  command ]  {} \;
  • path: 查找目录

    • ~表示$HOME目录
    • . 当前目录
    • / 根目录
  • -option:命令选项

    • -name xxx 使用某种文件名模式来匹配文件
      • find . -name "[A-Z]*" -print
    • -type b|d|c|p|l|f 查找某一类型的文件(块设备、目录、字符设备、管道、符号链接、普通文件)
      • find /etc -type d -print 在/etc目录下查找所有的目录
      • find . ! -type d -print 在当前目录下查找除目录以外的所有类型的文件
      • find /etc -type l -print 在/etc目录下查找所有的符号链接文件
    • -size n[c] 按照文件长度来查找文件查
      • 这里所指的文件长度既可以用块(block)或字节(byte)来计量
      • 在按照文件长度查找文件时,一般使用以字节表示文件长度
      • 在查看文件系统的大小时,一般使用块来计量
      • find . -size +1000000c -print 在当前目录下查找文件长度大于1 M字节的文件
      • find /home/apache -size 100c -print 在/home/apache目录下查找文件长度恰好为100字节的文件
      • find . -size +10 -print 在当前目录下查找长度超过10块的文件(一块等于512字节)
    • -perm 按照文件执行权限查找
      • -perm mode:文件许可正好符合mode
      • -perm +mode:文件许可部分符合mode
      • -perm -mode: 文件许可完全符合mode
      • eg: find . -perm 755 -print
    • -prune 指出需要忽略的目录
      • 如果同时使用-depth选项,那么-prune将被忽略
      • find [-path ..] [expression] (表达式按顺序求值)
      • eg:在/apps目录下查找不在bin子目录之内的所有文件
      • find /apps -path "/apps/bin" -prune -o -printfind /apps -path "/apps/bin" -a -prune -o -print等同
      • -a-o 都是短路求值,与 shell 的 && (and)和 || (or)类似
      • 伪码相当于: if -path "/usr/sam" then -prune else -print
      • find /usr/sam \(-path /usr/sam/dir1 -o -path /usr/sam/file1 \) -prune -o -name "temp" -print 避开多个文件夹,-name-o之后
    • -depth 首先匹配所有的文件然后再进入子目录中查找
      • 默认find将遍历所有子目录
      • 如果只想搜索当前目录,可以添加 -maxdepth 0 表示只检验命令行给定的文件
    • -follow 跟踪符号链接所指向的文件
    • -mount 查文件时不跨越文件系统mount点
      • find . -name "*.XC" -mount -print 从当前目录开始查找位于本文件系统中文件名以XC结尾的文件
    • -newer 查找比某个文件新或旧的文件
      • -newer f1 !f2 #查更改时间比f1新但比f2旧的文件
    • -ctime,-atime,-mtime 按文件 创建|访问|更改 时间来查找文件
      • -n指n天以内
      • +n指n天以前
    • -user xxx,nouser 按照文件属主来查找文件
      • find ~ -user sam -print
      • find /etc -user uucp -print 在/etc目录下查找文件属主为uucp的文件
      • find /home -nouser -print 查找属主帐户已经被删除的文件(即找到那些属主在/etc/passwd文件中没有有效帐户的文件)
    • -group xxx,nogroup 按文件所属于的用户组查找文件
      • find /apps -group gem -print
      • find / -nogroup -print 查找无有效所属组的文件(即该文件所属的组在/etc/groups中不存在)
  • -print: 将匹配的文件输出到标准输出

    • 只会输出从当前路径起的相对路径及文件名
  • -exec-ok: 执行shell命令,参数为匹配的文件
    • -exec command {} \;:将查到的文件执行command操作
    • -ok command {} \;: 与-exec一样,不过执行操作前会询问
    • 注意:必须要使用-print选项;{}\ 间有空格
    • find logs -type f -mtime +5 -exec rm { } \; 在/logs目录中查找更改时间在5日以前的文件并删除它们

注意:

使用-exec时,find命令将所有匹配到的文件一起传递给exec执行 可能会出现溢出错误(参数列太长”,“参数列溢出”,...) 可能会出现进程过多,系统性能下降的问题(有些系统中会为处理每一个匹配到的文件而发起一个相应的进程) 建议使用xargs分批获取和传入参数,且只有一个进程,eg:

# 查找系统中的每一个普通文件,然后使用xargs命令来测试它们分别属于哪类文件
> find . -type f -print | xargs file
./.kde/Autostart/Autorun.desktop: UTF-8 Unicode English text
./.kde/Autostart/.directory:      ISO-8859 text\
......

使用示例:

# 当前目录下查找所有用户具有读、写和执行权限的文件,并收回相应的写权限
find . -perm -7 -print | xargs chmod o-w

# 用grep命令在所有的普通文件中搜索hostname这个词
find . -type f -print | xargs grep "hostname"    

# 查找系统中所有文件长度为0的普通文件,并列出它们的完整路径
find / -type f -size 0 -exec ls -l {  } \;

# 让当前目录中文件属主具有读、写权限,并且文件所属组的用户和其他用户具有读权限的文件
find . -type f -perm 644 -exec ls -l {  } \;

# 查找/var/logs目录中更改时间在7日以前的普通文件,并在删除之前询问它们
find /var/logs -type f -mtime +7 -ok rm {  } \;    

#查找系统中所有属于root组的文件
find . -group root -exec ls -l {  } \;

# 删除当目录中访问时间在7日以来、含有数字后缀的admin.log文件
find . -name "admin.log[0-9][0-9][0-9]" -atime -7  -ok rm {  } \;

#查找当前文件系统中的所有目录并排序
find . -type d | sort

# 从当前目录开始,向下扫描查找类型是普通文件的所有.html文件
find -name "*.html" -type f    

# 返回文件权限和时间信息(-iname:表示区分大小写)
find -user chen -iname "*.html" -ls

# 在/logos 下查找5天内修改的普通日志文件并删除
find /logos -type f -mtime -5 -exec rm {} /;

#查找2004-11-30 16:36:37时更改过的文件
find ./ -name "*php" |  ls -l --full-time $A 2>/dev/null | grep "2004-11-30 16:36:37"

# 文件查找

find . -ctime +365  -type d -exec ls -ld {} \; >test.txt
find . -ctime +365  -type d -exec ls -ld {} \; >test.txt

find . -name "*.txt" -print 
find . -name *.* -ctime -365 -type d -exec mv {} temp/ \;
find . -name *.* -ctime -365 -type d -exec mv {} temp/ \;
find . -name *.gz -ctime -365 -exec ls -l {} \

find .  -type d -exec ls -ld {} \; >test.txt
find .  -type d -exec ls -ld {} \; >test.txt

xargs

xargs [-0epns] [ command [initial-arguments] ]

build and execute command lines from standard input

  • 字面意义上:x 是乘号,args 是 arguments (参数) ,则xargs的意思就是产生某个指令的参数
  • xargs 可读入 stdin 的资料,以空白字元或断行字元作分辨,将 stdin 的资料分隔成 args
    • 使用其他某个命令并将前一个命令的输出作为参数
    • 将参数列表转换成小块分段传递给其他命令,以避免参数列表过长的问题
  • xargs本身虽然没有多大用处,但在与其他命令相结合时,它的功能非常强大
  • 注意:因为是以空白字元作为分隔,所以如果有一些档名或者是其他意义的名词内含有空白字元的时候,xargs 可能会误判

參數:

  1. -i 选项告诉xargs用每项的名称替换{}

     find ./ -type f -print | xargs -i mv -f {} ./newdir
    
  2. -t选项指示xargs先打印要运行的命令,然后再执行

      ls | xargs -t -i mv {} {}.bak
      cat listFile | xargs -t -i ls ~/re-extract/"{}"
    
  3. -0 将输入的特殊字元(例如,, \, 空白键等)还原成一般字元,可用于正确地处理了新行和空格

     # 查找tmp目录下以core命名的文件,然后删除
    
     # 如果文件名字包含新行或者空格的话,这条命令将会被错误操作
      > find /tmp -name core -type f -print | xargs /bin/rm -f
    
     # 这条命令就正确地处理了新行和空格,有可能带来的错误
     > find /tmp -name core -type f -print0 | xargs -0 /bin/rm -f
    
  4. -p 它使操作具有可交互性,在执行每个指令的 argument 时,都会询问使用者的意思:

    # xarg要求在运行每个命令之前进行确认,按下"y",则执行
    file * | grep ASCII | cut -d":" -f1 | xargs -p vi 
    vi alert_DBA102.log dba102_cjq0_14493.trc dba102_mmnl_14497.trc dba102_reco_14491.trc dba102_rvwr_14518.trc ?...
    
  5. -r 如果没有要运行的内容,该命令退出:

    file * | grep SSSSSS | cut -d":" -f1 | xargs -t -r wc -l $
    
  6. -n 指定每次从输入源中取几行数据(限制单个命令行的参数个数):

     # 限制每个命令行仅使用两个参数
     file * | grep ASCII | cut -d":" -f1 | xargs -t -n2 ls -ltr
    
  7. -e : EOF (end of file) 后面可接一个字串,代表结束标识(当 xargs 分析到这个字串时,就会停止继续工作)

    # 当分析到 lp 就结束这串指令 (注意 -e'lp' 是连在一起的,中间没有空白键)
    cut -d':' -f1 < /etc/passwd | xargs -e'lp' finger
    
  8. -s : 每次的输出的最大bytes

示例:

  1. /etc/passwd 的第一栏取出,仅取三行,使用 finger 这个指令秀出每个帐号内容

    • 由 finger account 可以取得该帐号的相关说明内容
    • 利用 cut 取出帐号名称
    • 用 head 取出三个帐号
    • 由 xargs 将三个帐号的名称变成 finger 后面需要的参数

      > cut -d ':' -f1 < /etc/passwd | head -n 3 | xargs finger    
      
      Login name: root                        In real life: Super-User
      Directory: /                            Shell: /sbin/sh
      Last login Thu Jan  5 08:44 on pts/2 from 10.7.82.110
      New mail received Sun Feb  5 14:00:26 2012;
      unread since Thu Feb 21 11:53:16 2008
      No Plan.
      
      Login name: daemon
      Directory: /
      Never logged in.
      No unread mail
      No Plan.
      
      Login name: bin
      Directory: /usr/bin
      Never logged in.
      No unread mail
      No Plan.
      
  2. 删除数量比较多的文件

    • ls 输出所有的文件名(用空格分割)
    • xargs将ls的输出,每20个为一组(以空格为分隔符),作为rm -rf的参数
    • 即将所有文件名20个为一组,由rm -rf删除,这样就不会超过命令行的长度了
      ls | xargs -n 20 rm -fr
      
  3. 迁移文件

     cat temp.txt | xargs -n1 -i mv {} bak/
     ls *100[9]* | xargs -t -i mv {} "/db/data/autoftp/sent/tsmc/stdfbak/"
     ls *100[7]*.gz | xargs -t -i -n1  mv {} "/db/data/autoftp/sent/tsmc/stdfbak/"{}
    
  4. xargsgrep使用比较

    • XXX | grep –i ‘hello’
      • grep通过管道读取XXX的输出结果,并在该结果中搜索hello
    • XXX | xargs grep –i ‘hello’
      • xargs通过管道读取XXX的输出结果,并将该结果作为grep的最后的FILE参数
      • grep –i ‘hello’ 组合成完整的命令(如 grep –i ‘hello’ stdio.h stdlib.h)后,执行
      • 例如:find . -name "*.foo" | xargs grep bar大体等价于grep bar `find . -name "*.foo"`
    • 两者对于管道的输出作不同的处理:
      • 前者是grep直接从stdin中读取管道数据,并搜索。
      • 后者是xargs直接从stdin中读取管道数据,并和grep –i ‘hello’组合,然后调用exec执行该命令

awk

文本分析工具

nawk '/pattern/{action}' filename
cmd | nawk '/pattern/{action}' filename
  • 把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理
  • pattern 表示 AWK 在数据中查找的内容,可使用正则表达式(正则表达式需用斜杠括起来)
  • action 是在找到匹配内容时所执行的一系列命令
  • -F 域分隔符,默认是空格
  • 内置变量:

    • ARGC 命令行参数个数
    • ARGV 命令行参数数组
    • ENVIRON 支持队列中系统环境变量的使用
    • FILENAME awk浏览的文件名
    • FNR 浏览文件的记录数
    • NF 当前记录中的字段数(记录域个数)
    • NR 当前已读的记录数
    • OFS 设置输出域分隔符,默认为空格
    • FS 设置输入域分隔符,默认为空格,/,跳個符(等价于命令行 -F选项)
    • ORS 输入记录分隔符
    • RS 输出记录分隔符
    • OFMT 控制打印數,默認為 %.6g(打印精確到小數點后6位)
    • $0 整條記錄
    • $1 表示当前行的第一个域
  • 內置函数

    • sub,gsub,length,match,split
    • 算数运算函数:int,log,sin,sqrt,rand,srand
    • 打印输出函数:print,printf
      • print \b,\f,\n,\r,\t,\c
      • printf %c,%d,%e,%f,%o,%s,%x 格式化特制的輸出
      • eg:
        {print "\t\tHave a nice day," $1,$2 "\!"}
        {printf "%The name is: -15s ;ID is %8d\n",$1,$3}
        
    • 用户自定义函数
  • 示例:

      # pattern
      nawk '/Mary/' file1.txt
      nawk '$1 ~ /[Bb]ill/' file2.txt
    
      # action:print
      nawk '{print $1,$2}' file1.txt
      nawk  '/^[A-Z][a-z]+/{print "Hello "$0}' file1.txt
    
      # -F
      nawk -F: '/Tom Jones/{print $0,NF}' file1.txt
      nawk -F'[ :\t]' '/Tom Jones/{print $0,NF}' file1.txt
    
      # argv
      nawk 'BEGIN{print substr(ARGV[1],11,1)}' $argv[2]
    
      # cmd | awk
      ps -ef | grep ftp | grep Feb | awk '{print $11}' | uniq | more
    
      # 批量重命名
      ls *.tar | awk -F"." '{print $1"."$2"."$3"."$4,$1"."$2"."$3".1"}'| xargs -n2 mv
      ls * | awk -F"." '{print $1"."$2"."$3,$1"."$2}' | xargs -n2 mv
      ls * | awk -F"." '{print $1"."$2"."$3,$1"."$2"."$3".1"}' | xargs -n2 mv
    

示例:

  1. 解析文档(关联数组,统计,printf,算数运算,sort应用)

     #! /bin/csh
      echo Begin
      set resultFile = myResult.txt
      # get head 
      #head -8 Testdata.log | awk -F, '{print $1":"$2}'     > $resultFile
      awk -F, 'NR==1 {print $1":"$2 }' Testdata.log    > $resultFile
      nawk -F, 'NR==2 {print $1":"tolower($2) }' Testdata.log >> $resultFile
      awk -F, 'NR==3,NR==8 {print $1":"$2 }' Testdata.log >> $resultFile
    
      echo StartDate:`awk -F, 'NR==9{print $2}' Testdata.log | cut -c1-8`  >> $resultFile
      echo StartTime:`awk -F, 'NR==9{print $2}' Testdata.log | cut -c9-14` >> $resultFile
    
     # get Passdie,Grossdie,Yeild
     awk -F, 'NR>10 { grossdie++;if($5=="P") count++}END
     {printf("Passdie:%d\nGrossdie:%d\nYield:%.2f\n\n",count,grossdie,count/grossdie*100)} ' Testdata.log     >>$resultFile
    
     # get x,y,bin,site,status,[ bin Summary ]
     awk -F, 'NR>10{print "x="$1,"y="$2,"bin="$3,"site="$4,"status="$5}' Testdata.log >> $resultFile
     echo >> $resultFile
     echo "[bin summary]" >> $resultFile
     echo >> $resultFile
     awk -F, 'NR>10{count[$3]++;}END{for(i in count){print "bin"i":"count[i] | "sort -t: +0.3n"}}' Testdata.log      >> $resultFile
     echo End\!
     exit
    
     awk -F, 'NR>10{count[$3]++; print "x="$1,"y="$2,"bin="$3,"site="$4,"status="$5 }END{ printf("\n[bin     summary]\n"); for(i in count){print "bin"i":"count[i] | "sort -t: +0.3n" };Close "sort -t: +0.3n"}' Testdata.log
    
  2. 根据传入参数去除重复行

    • 输入源

        > cat uniqueTest.txt
      
        222|15|2401668|3273877|4114|1|
        222|15|2401444|3273847|3274|1|
        222|15|2401444|32722200|4124|1|
        222|15|2401474|32253847|7419|1|
      
    • 去除重复的行

        # 根据第三列判断重复行
        > awk -F"|" '{a[$3]=$0}END{for (i in a) print a[i]}'  uniqueTest.txt
      
        222|15|2401444|32722200|4124|1|
        222|15|2401474|32253847|7419|1|
        222|15|2401668|3273877|4114|1|
      
        # 根据第三第四列组合判断重复行
        > awk -F"|" '{a[$3$4]=$0;b[$3$4]=NR}END{for (i in a) print b[i] " " a[i]}'  uniqueTest.txt
      
        3 222|15|2401444|32722200|4124|1|
        2 222|15|2401444|3273847|3274|1|
        4 222|15|2401474|32253847|7419|1|
        1 222|15|2401668|3273877|4114|1|
      
    • 传入参数
        > set xField = 3
        > set yField=4
        > awk -F"|" '{a[$x$y]=$0;b[$x$y]=NR}END{for (i in a) print b[i] " " a[i]}' x="$xField" y="$yField" uniqueTest.txt
      
  3. BEGIN/END

    • 测试数据:
        docker@default:~$ cat /etc/passwd
        root:x:0:0:root:/root:/bin/sh
        lp:x:7:7:lp:/var/spool/lpd:/bin/sh
        nobody:x:65534:65534:nobody:/nonexistent:/bin/false
        tc:x:1001:50:Linux User,,,:/home/tc:/bin/sh
        dockremap:x:100:101:Linux User,,,:/home/dockremap:/bin/false
        docker:x:1000:50:Linux User,,,:/home/docker:/bin/sh
      
    • 显示/etc/passwd的账户name和账户对应的shell, 第一行添加列名"name,shell", 最后一行添加"blue,/bin/nosh"
        docker@default:~$ cat /etc/passwd |awk  -F ':'  'BEGIN {print "name,shell"}  {print $1","$7} END {print "blue,/bin/nosh"}'
        name,shell
        root,/bin/sh
        lp,/bin/sh
        nobody,/bin/false
        tc,/bin/sh
        dockremap,/bin/false
        docker,/bin/sh
        blue,/bin/nosh
      
    • 显示文件名filename,行号linenumber,列数columnes,每行内容linecontent
        # 使用printf替代print,更加简洁
        # eg:awk  -F ':'  '{printf("filename:%10s,linenumber:%s,columns:%s,linecontent:%s\n",FILENAME,NR,NF,$0)}' /etc/passwd
        docker@default:~$ awk  -F ':'  '{print "filename:" FILENAME ",linenumber:" NR ",columns:" NF ",linecontent:"$0}' /etc/passwd
        filename:/etc/passwd,linenumber:1,columns:7,linecontent:root:x:0:0:root:/root:/bin/sh
        filename:/etc/passwd,linenumber:2,columns:7,linecontent:lp:x:7:7:lp:/var/spool/lpd:/bin/sh
        filename:/etc/passwd,linenumber:3,columns:7,linecontent:nobody:x:65534:65534:nobody:/nonexistent:/bin/false
        filename:/etc/passwd,linenumber:4,columns:7,linecontent:tc:x:1001:50:Linux User,,,:/home/tc:/bin/sh
        filename:/etc/passwd,linenumber:5,columns:7,linecontent:dockremap:x:100:101:Linux User,,,:/home/dockremap:/bin/false
        filename:/etc/passwd,linenumber:6,columns:7,linecontent:docker:x:1000:50:Linux User,,,:/home/docker:/bin/sh
      
    • 可自定义变量,{action}可以有多个语句,以;号隔开

        docker@default:~$ awk '{count++;print $0;} END{print "user count is ", count}' /etc/passwd
        root:x:0:0:root:/root:/bin/sh
        lp:x:7:7:lp:/var/spool/lpd:/bin/sh
        nobody:x:65534:65534:nobody:/nonexistent:/bin/false
        tc:x:1001:50:Linux User,,,:/home/tc:/bin/sh
        dockremap:x:100:101:Linux User,,,:/home/dockremap:/bin/false
        docker:x:1000:50:Linux User,,,:/home/docker:/bin/sh
        user count is  6
      
        docker@default:~$ awk 'BEGIN {count=0;print "[start]user count is ", count} {count=count+1;print $0;} END{print "[end]user count is ", count}' /etc/passwd
        [start]user count is  0
        root:x:0:0:root:/root:/bin/sh
        lp:x:7:7:lp:/var/spool/lpd:/bin/sh
        nobody:x:65534:65534:nobody:/nonexistent:/bin/false
        tc:x:1001:50:Linux User,,,:/home/tc:/bin/sh
        dockremap:x:100:101:Linux User,,,:/home/dockremap:/bin/false
        docker:x:1000:50:Linux User,,,:/home/docker:/bin/sh
        [end]user count is  6
      
    • 收集信息存储到数组, 下标可以是数字和字母( 存储在内部的一张hash表里,即非顺序存储)
        docker@default:~$ awk -F ':' 'BEGIN {count=0;} {name[count] = $1;count++;}; END{for (i = 0; i < NR; i++) print i, name[i]}' /etc/passwd
        0 root
        1 lp
        2 nobody
        3 tc
        4 dockremap
        5 docker
      

sed

sed [-nefri] [command]

说明:

  1. Options: [-nefri]

    • -n : 使用安静(silent)模式。在一般sed的用法中,所有来自STDIN的资料一般都会被列出到屏幕上。加上-n后,则只有经过sed 特殊处理的那一行(或者动作)才会被列出来
    • -e∶多点编辑,等价于--expression
        # 同 /sbin/ifconfig | grep 'inet ' | sed 's/inet//g' | sed 's/netmask.*//g'
        >  /sbin/ifconfig | grep 'inet ' | sed -e 's/inet //g' -e 's/ netmask.*//g'
        172.17.0.2
        127.0.0.1
      
    • -f∶指定sed脚本的文件名。 直接将sed的动作写在一个档案内,-f filename 则可以执行filename内的sed动作
    • -r∶sed 的动作支援的是延伸型正则表达式的语法。(预设是基础正则表达式语法)
    • -i∶直接修改读取的文件内容,而不是由屏幕输出
         # 直接在文件最后一行加入“This is a test”
         >  cat 1.txt
         AAA
         BBB
         CCC
         >  sed -i '$a This is a test' 1.txt
         >  cat 1.txt
         AAA
         BBB
         CCC
         This is a test
      
  2. Command: :[n1[,n2]]function

    • a\∶ 新增。后面可接字串,在当前行下面插入
        >  nl /etc/passwd | sed '2a drink tea'
        1    root:x:0:0:root:/root:/bin/bash
        2    bin:x:1:1:bin:/bin:/sbin/nologin
        drink tea
        3    daemon:x:2:2:daemon:/sbin:/sbin/nologin
        4    adm:x:3:4:adm:/var/adm:/sbin/nologin
      
        # 加入两行,中间用‘\’换行输入或使用‘\n’来进行新行的添加:
        >  nl /etc/passwd | sed '2a Drink tea or ......\
        drink beer ?'
        1    root:x:0:0:root:/root:/bin/bash
        2    bin:x:1:1:bin:/bin:/sbin/nologin
        Drink tea or ......
        drink beer ?
        3    daemon:x:2:2:daemon:/sbin:/sbin/nologin
        4    adm:x:3:4:adm:/var/adm:/sbin/nologin
      
    • i\∶ 插入。后面可以接字串,在当前行上面插入文本
        >  nl /etc/passwd | sed '2i drink tea'
        1    root:x:0:0:root:/root:/bin/bash
        drink tea
        2    bin:x:1:1:bin:/bin:/sbin/nologin
        3    daemon:x:2:2:daemon:/sbin:/sbin/nologin
        4    adm:x:3:4:adm:/var/adm:/sbin/nologin
      
    • c\∶替换行。后面可以接字串,把选定的行改为新的文本
        # 将第2-4行的内容取代成为"No 2-4 number"
        >  nl /etc/passwd | sed '2,4c No 2-4 number'
        1    root:x:0:0:root:/root:/bin/bash
        No 2-4 number
        5    lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
        6    sync:x:5:0:sync:/sbin:/bin/sync
      
    • s∶ 替换行中字符。可以直接进行替换指定字符。通常这个s的动作可以搭配正则表达式。例如 1,20s/old/new/g

        >  /sbin/ifconfig | grep 'inet '
        inet 172.17.0.2  netmask 255.255.0.0  broadcast 0.0.0.0
        inet 127.0.0.1  netmask 255.0.0.0
      
        >  /sbin/ifconfig | grep 'inet ' | sed 's/inet //g'
        172.17.0.2  netmask 255.255.0.0  broadcast 0.0.0.0
        127.0.0.1  netmask 255.0.0.0
      
        >  /sbin/ifconfig | grep 'inet ' | sed 's/inet//g' | sed 's/netmask.*//g'
        172.17.0.2
        127.0.0.1
      
    • g: 全局搜索。整行匹配的都替换,没有g则只替换一行中第一个匹配的内容,当需要从第N处匹配开始替换时,可以使用/Ng
        sed 's/book/books/g' file
        sed 's/book/books/2g' file
      
    • y :把一个字符翻译为另外的字符(不能用正则表达式)
        # 把1~10行内所有abcde转变为大写
        sed '1,10y/abcde/ABCDE/' file
      
    • d :删除。后面通常不接任何内容
        sed '2d' datafile     # 删除第2行
        sed '$d' datafile     # 删除最后一行    
        sed '2,$d' datafile   # 删除第2行~末尾所有行
        sed '2,5d' datafile                 # 删除2~5行
        sed '/My/,/You/d' datafile         # 删除包含My的行~You的行的内容
        sed '/My/,10d' datafile            # 删除包含My的行~第10行的内容
        sed '/^test/'d datafile            # 删除文件中所有开头是test的行
        nl /etc/passwd | sed  '/root/d'  # 删除包含root的行
      
    • p∶ 列印。将某个选择的资料印出。通常p会与参数-n 一起用
        sed -n '3p' datafile           # 打印第3行
        sed -n '100,200p' datafile     # 打印100~200行
        chenjindeMacBook-Pro:~ cj$  nl /etc/passwd | sed -n '5,9p'
        5    # in single-user mode.  At other times this information is provided by
        6    # Open Directory.
        7    #
        8    # See the opendirectoryd(8) man page for additional information about
        9    # Open Directory.
      
    • n: 下一行。匹配行的下一行

        # 打印匹配字符串的下一行
        > sed -n '/AAA/{n;p}' 1.txt    
        BBB
        CCC
        EEE
      
        # 替换匹配行的下一行中的BBB为bbb,打印所有行
        > sed '/AAA/{ n; s/BBB/bbb/; }' 1.txt 
        AAA
        bbb
        CCC
        AAA
        CCC
        DDD
        AAA
        EEE
      
        # 注意以下结果不一样
        > sed '/AAA/{ n; s/BBB/bbb/; }' 1.txt    # 对匹配AAA的下一行进行BBB匹配修改,打印所有行
        > sed '/AAA/{ n; s/BBB/bbb/;p}' 1.txt    # 对匹配AAA的下一行进行BBB匹配修改,打印所有匹配AAA的下一行
        > sed '/AAA/{ n; s/BBB/bbb/p }' 1.txt    # 对匹配AAA的下一行进行BBB匹配修改,打印所有匹配AAA的下一行中匹配BBB替换修改的行
      
    • q:退出

        # 打印完第10行后,退出
        >  sed '5q' 1.txt
        AAA
        BBB
        CCC
        AAA
        CCC
      
    • 保持空间:

      • h: 拷贝模板块的内容到内存中的缓冲区
      • H: 追加模板块的内容到内存中的缓冲区
      • g: 获得内存缓冲区的内容,并替代当前模板块中的文本
      • G: 获得内存缓冲区的内容,并追加到当前模板块文本的后面
      • x: 表示互换模板块中的文本和缓冲区中的文本

        > cat 1.txt
        AAA a
        BBB b
        CCC c
        AAA 1
        CCC 3
        DDD 4
        AAA 1
        EEE 5
        
        # 任何包含AAA的行都被复制并追加到该文件的末尾,只保留最后一个匹配行
        > sed -e '/AAA/h' -e '$G' 1.txt 
        AAA a
        BBB b
        CCC c
        AAA 1
        CCC 3
        DDD 4
        AAA 1
        EEE 5
        AAA 1
        
        # 任何包含AAA的行都被复制并追加到该文件的末尾,追加了所有匹配行
        > sed -e '/AAA/H' -e '$G' 1.txt 
        AAA a
        BBB b
        CCC c
        AAA 1
        CCC 3
        DDD 4
        AAA 1
        EEE 5
        AAA a
        AAA 1
        AAA 1
        
        # 把包含AAA的行与CCC行一对一互换
        > sed -e '/AAA/h' -e '/CCC/x' 1.txt 
        AAA a
        BBB b
        AAA a
        AAA 1
        AAA 1
        DDD 4
        AAA 1
        EEE 5
        
  3. 表达式元字符

    • ^ 匹配行开头,eg: ^abc 匹配以abc开头的行
    • $ 匹配行结尾,eg:abc$ 匹配以abc结尾的行
    • . 匹配非换行符的任意一个字符,eg:a.c 可以匹配abc,adc,a8c,...
    • * 匹配任意多个字符,eg: a*c 可以匹配 ac,abc,adc,abdc,...
    • + 匹配某字符出现一次及以上次字符,eg:a+ 可以匹配 a,aa,aaa,aaaa,...
    • ? 匹配0次或一次字符,eg:a? 可以匹配 b,a
    • [] 匹配一个指定范围内的字符
        [ABC]de     # 可以匹配Ade,Bde,Cde; 
        [A-Ca-c]     #与A-C及a-c范围内的字符匹配; 
        [ABC][DEF]     #匹配AD,AE,AF,BD,DE,BF,CD,CE,CF
      
    • [^] 匹配一个不在指定范围内的字符,eg: [^ABC] 可以匹配不以A或B或C字母开头的行
    • | 匹配或
        Desk|Chair             #与Desk和Chair中的任一个匹配;
        (Blue|Black)Berry: #匹配BlueBerry或BlackBerry
      
    • {} 匹配次数
        a{3} 匹配 aaa; 
        a{3,5} 匹配 aaa,aaaa,aaaaa; 
        a{3,} 匹配 aaa,aaaa,aaaaa,aaaaaaa,....
        /a\{5,10\}/ 匹配5~10个a的行
      
    • \(..\) 匹配子串,并保存匹配的字符。对于匹配到的第一个子串就标记为 \1,依此类推匹配到的第二个结果就是 \2
        > echo "this is digit 7 in a number" | sed 's/digit \([0-9]\)/\1/'
        this is 7 in a number
        > echo "loveable" | sed 's/\(love\)able/\1rs/'
        lovers
      
    • & 保存匹配到的字符

        > echo "this is a test line" | sed 's/\w\+/[&]/g'  # 正则表达式 \w\+ 匹配每一个单词,使用 [&] 替换它,& 对应于之前所匹配到的单词
        [this] [is] [a] [test] [line]
      
        > sed 's/^192.168.0.1/&localhost/' file        # 所有以192.168.0.1开头的行都会被替换成它自已加localhost
        192.168.0.1localhost Hello
        192.210.0.1 Do you know
        192.168.0.1localhost World
      
    • \< 匹配单词的开始
    • \> 匹配单词的结束,eg: /love\>/ 匹配包含以love结尾的单词的行
  4. 注意:

    • \s 匹配任意的空白符,包括空格,制表符(Tab),换行符,中文全角空格
    • \S 匹配任意不是空白符的字符
    • .* 在使整个表达式能得到匹配的前提下,匹配尽可能多的字符(贪婪匹配) eg: aabab -> a.*b -> aabab
    • .*? 在使整个表达式能得到匹配的前提下,匹配尽可能少的字符(懒惰匹配) eg: aabab -> a.*?b -> aab,ab
    • 定址:
      • 决定对哪些行进行编辑(可以是数字、正则表达式、或二者的结合,默认为输入文件的所有行。
      • 注:数字表示行号,$表示最后一行
    • 定界符:
      • 命令中字符 / 在sed中作为定界符使用,也可以使用任意的定界符, 定界符出现在样式内部时,需要使用\进行转义
    • 引用:sed表达式可以使用单引号''来引用,但是如果表达式内部包含变量字符串,就需要使用双引号""
        set test=Hello
        echo "Hello WORLD,How are you?" | sed "s/$test/HELLO"
        HELLO WORLD
      

示例:

# <SGUID isNull="true"></SGUID>` => `<SGUID>xxxxxxxx</SGUID>
> echo "<SGUID>1234AJD839D</SGUID>" | sed -e 's|<SGUID>[0-9A-Z]\{1,\}</SGUID>|<SGUID isNull="true"></SGUID>|g'
<SGUID>xxxxxxxx</SGUID>
> cat a.txt
<Test bind_variables="{A=801,B=DD Flex}" view_criteria="[PrimaryKeyCriteria]" partitionkey_value="ABC"/>

> grep -oP "bind_variables=[^\s]\{.*?\}[^\s]" a.txt
bind_variables="{A=801,B=DD Flex}"
> grep -oP "bind_variables=[^\s]\{.*?\}[^\s]" sdf.txt | sed 's/{\(.*\)}/\1/g'
bind_variables="A=801,B=DD Flex"
> grep -oP "bind_variables=[^\s]\{.*?\}[^\s]" sdf.txt | awk -F'[{}]' '{print $2}'
A=801,B=DD Flex

> grep -oP "view_criteria=[^\s]\[.*?\][^\s]" sdf.txt
view_criteria="[PrimaryKeyCriteria]"
> grep -oP "view_criteria=[^\s]\[.*?\][^\s]" sdf.txt | awk -F'[][]' '{print $2}'
PrimaryKeyCriteria

> grep -oP "partitionkey_value=[^\s]\w+[^\s]" sdf.txt
partitionkey_value="ABC"
> grep -oP "partitionkey_value=[^\s]\w+[^\s]" sdf.txt | awk -F'[""]' '{print $2}'
ABC
> grep -oP "partitionkey_value=[^\s]\w+[^\s]" sdf.txt | awk -F= '{print $2}' | sed s/\"/\'/g
'ABC'

uniq

> uniq --help
  -c, --count           prefix lines by the number of occurrences             在每行前面显示该行重复次数
  -d, --repeated        only print duplicate lines, one for each group        只输出重复的行
  -D, --all-repeated[=METHOD]  print all duplicate lines                      只输出重复的行,有几行输出几行
                          groups can be delimited with an empty line
                          METHOD={none(default),prepend,separate}
  -f, --skip-fields=N   avoid comparing the first N fields                    忽略的段数,eg: -f 1 忽略第一段
      --group[=METHOD]  show all items, separating groups with an empty line
                          METHOD={separate(default),prepend,append,both}
  -i, --ignore-case     ignore differences in case when comparing            不区分大小写
  -s, --skip-chars=N    avoid comparing the first N characters               忽略N个字符
  -u, --unique          only print unique lines                              去除重复的后,全部显示出来,即列出唯一项
  -z, --zero-terminated  end lines with 0 byte, not newline
  -w, --check-chars=N   compare no more than N characters in lines           只检查N个以内的字符,之外的不做对照

示例:

测试数据:

>  cat test.txt
this is a test
this is a test
this is a test
i am tank
i love tank
i love tank
this is a test
whom have a try
WhoM have a try
you  have a try
i want to abroad
those are good men
we are good men
  1. -c 在每行前面显示该行重复次数,注意:检查重复行的时候,只会检查相邻的行
     >  uniq -c test.txt
     3 this is a test
     1 i am tank
     2 i love tank
     1 this is a test
     1 whom have a try
     1 WhoM have a try
     1 you  have a try
     1 i want to abroad
     1 those are good men
     1 we are good men
    
  2. 排序后统计重复次数(解决只用-c统计的不准确问题)
     >  sort test.txt | uniq -c
     1 WhoM have a try
     1 i am tank
     2 i love tank
     1 i want to abroad
     4 this is a test
     1 those are good men
     1 we are good men
     1 whom have a try
     1 you  have a try
    
  3. -d 只输出重复的行
     >  uniq -d -c test.txt
     3 this is a test
     2 i love tank
    
  4. -D 只输出重复的行,有几行输出几行,注意:不能和-c一起使用
     >  uniq -D test.txt
     this is a test
     this is a test
     this is a test
     i love tank
     i love tank
    
  5. -f 忽略第某列统计

     >  uniq -f 1 -d -c test.txt
     3 this is a test
     2 i love tank
     2 whom have a try
     2 those are good men
    
     >  uniq -f 1 -D test.txt
     this is a test
     this is a test
     this is a test
     i love tank
     i love tank
     whom have a try
     WhoM have a try
     those are good men
     we are good men
    
  6. -s 忽略前4个字符进行统计
     >  uniq -s 4 -D test.txt
     this is a test
     this is a test
     this is a test
     i love tank
     i love tank
     whom have a try
     WhoM have a try
     you  have a try
    
  7. -w 只统计前2个字符
     >  uniq -w 2 -D test.txt
     this is a test
     this is a test
     this is a test
     i am tank
     i love tank
     i love tank
    
  8. -i 忽略大小写
     >  uniq -i -D test.txt
     this is a test
     this is a test
     this is a test
     i love tank
     i love tank
     whom have a try
     WhoM have a try
    
  9. -u 列出唯一项(count为1)

     >  uniq -u test.txt
     i am tank
     this is a test
     whom have a try
     WhoM have a try
     you  have a try
     i want to abroad
     those are good men
     we are good men
    
     >  uniq -u -i test.txt
     i am tank
     this is a test
     you  have a try
     i want to abroad
     those are good men
     we are good men
    

curl

Command Line URL viewer,是一种命令行工具,用来发送网络请求

-#, --progress-bar             Make curl display a simple progress bar instead of the more informational standard meter.
-b, --cookie <name=data>       Supply cookie with request. If no =, then specifies the cookie file to use (see -c).
-c, --cookie-jar <file name>   File to save response cookies to.
-d, --data <data>              Send specified data in POST request. Details provided below.
-f, --fail                     Fail silently (don not output HTML error form if returned).
-F, --form <name=content>      Submit form data.
-H, --header <header>          Headers to supply with request.
-i, --include                  Include HTTP headers in the output.
-I, --head                     Fetch headers only.
-k, --insecure                 Allow insecure connections to succeed.
-L, --location                 Follow redirects.
-o, --output <file>            Write output to . Can use --create-dirs in conjunction with this to create any directories specified in the -o path.
-O, --remote-name              Write output to file named like the remote file (only writes to current directory).
-s, --silent                   Silent (quiet) mode. Use with -S to force it to show errors.
-v, --verbose                  Provide more information (useful for debugging).
-w, --write-out <format>       Make curl display information on stdout after a completed transfer. See man page for more details on available variables. Convenient way to force curl to append a newline to output: -w "\n" (can add to ~/.curlrc).
-X, --request                  The request method to use.
  1. 显示:-i / -l / -v / --trace

     curl -i www.example.com                      # 显示全部信息
     curl -l www.example.com                      # 只显示头部信息
     curl -v www.example.com                      # 显示一次请求全过程解析
     curl --trace output.txt www.example.com      # 可显示更详细的通信过程
    
  2. HTTP Method:-X

     curl -X GET www.example.com     # 同 curl www.example.com
     curl -X PUT www.example.com
     curl -X POST www.example.com
     curl -X DELETE www.example.com
    
  3. 指定发送数据:-d ( --data ) / --data-urlencode (自动转义特殊字符) / -F (--form)

     # curl -X POST -d "username=Tom&password=123" http://www.example.com/login  # 使用了-d,默认即POST方法,可省略 -X POST
     curl -d "username=Tom&password=123" http://www.example.com/login 
    
     # curl http://www.example.com/login?username=Tom&password=123
     curl -G -d "username=Tom&password=123" http://www.example.com/login  
    
     # PUT
     curl -X PUT -d "username=Tom&password=345" http://www.example.com/change
    
     curl --data @localFilename http://www.example.com/login
    
     curl -X POST -F 'username=Tom' -F 'password=123' http://www.example.com/login
    
    • -dapplication/x-www-url-encoded方式
    • -Fmultipart/form-data方式
    • 注意:如果在一次curl中同时使用-d-F选项会报Warning: You can only select one HTTP request!的警告,导致指令无法执行
  4. 自定义头信息:-H (--header)

     curl  -H "Content-Type: application/json" -X POST -d '{"key1":"value1", "key2":"value2"}' http://localhost:3000/data
    
  5. 文件上传: -F (--form) ,request会添加 enctype="multipart/form-data" / -T ( --upload-file <file> )

     <!DOCTYPE html>
     <meta charset="utf-8">
     <body>
     <form method="POST" action='/submit' enctype="multipart/form-data">
     <input type="text" name="user"><br>
     <input type="file" name="img"><br>
     <input type="submit">
     </form>
    
     curl --form img=@localFilename --form user=Tom http://www.example.com/submit
     curl -F 'img=@localFilename' http://www.example.com/submit?user=Tom
    
     curl -F 'fileX=@pathToFileX' -F 'fileY=@pathToFileY' http://www.example.com/upload      # Upload multiple files
     curl -F 'files[]=@pathToFileX' -F 'files[]=@pathToFileY' http://www.example.com/upload  # Upload an array of file
    
     curl -u ftpuser:ftppass -T myfile.txt ftp://ftp.testserver.com        # 将myfile.txt文件上传到服务器
     curl -u ftpuser:ftppass -T "{file1,file2}" ftp://ftp.testserver.com   # 同时上传多个文件
     curl -u ftpuser:ftppass -T - ftp://ftp.testserver.com/myfile_1.txt    # 从标准输入获取内容保存到服务器指定的文件中
    
  6. 下载文件: -o <filename> 指定保存文件 / -O 直接使用URL中文件名保存 / > 重定向,保存响应结果到指定路径的文件中

     curl -o mytest.txt http://www.example.com/test.html
     curl -O http://www.example.com/test.html
     curl http://www.example.com/test.html > index.html
    
     curl -o filename1 URL1 -o filename2 URL2                    # 同时下载多个文件
     curl -O URL1 -O URL2
    
     curl -u ftpuser:ftppass -O ftp://ftp_server/public_html/           # 列出public_html下的所有文件夹和文件
     curl -u ftpuser:ftppass -O ftp://ftp_server/public_html/xss.php    # 下载xss.php文件
    
  7. cookie: -c 保存cookie信息 / -D 保存整个header信息,包括cookie / -b 携带cookie信息发送请求

     curl -c cookie.txt -d "username=Tom&password=123" http://www.example.com/login
     curl -b cookie.txt http://www.example.com/admin
    
  8. 跳转:-L 表示追踪重定向 / -e(--referer) 在http request头信息中,增加一个referer字段,表示来源网址

     curl -L http://www.example.com/login
     curl -e http://www.yourblog.com http://www.example.com    # 会让服务器其以为你是从http://www.yourblog.com点击某个链接过来的
    
  9. User Agent: -A (--user-agent) 自定义用户代理

     # 客户端的设备信息。服务器有时会根据这个字段,针对不同设备,返回不同格式的网页,比如手机版和桌面版
     curl -A “Mozilla/5.0 (Android; Mobile; rv:35.0) Gecko/35.0 Firefox/35.0” http://www.baidu.com   # 伪装成安卓火狐浏览器对网页进行请求
     curl URL -A "Mozilla/5.0"
     curl URL --user-agent "Mozilla/5.0"
    
  10. 认证: -u (--user) 设置服务器的用户名和密码,可用于HTTP,FTP的认证

    curl -u user:pwd URL    # 可以指定密码
    curl -u user URL        # 可在后续操作中输入密码
    

示例:

curl -i -H "Content-Type:application/json" -X POST -d '{"name": "cj", "password":"123456"}' http://127.0.0.1:8080/micro-auth/login
curl -i -H "Content-Type:application/json" -H "micro-auth:1184e49a-8271-4de7-9323-c5f8c81c7cac" -X POST http://127.0.0.1:8080/micro-auth/authentication

crontab

基本格式:M H D m d cmd

  • M: 分鐘(0-59)
  • H: 小時(0-23)
  • D: 天(1-31)
  • m: 月(1-12)
  • d: 一星期內的天(0~6,0為星期天)
  • cmd:要運行的程序,程序被送入shell執行
  • 例如:
    # MIN   HOUR   DAY   MONTH   DAYOFWEEK  COMMAND
    10         6          *           *           *               date       test.sh # 每天早上6:10   
    0         */2         *           *           *               date       test.sh # 每隔两小时
    0     23-7/2,8         *          *           *               date  test.sh # 晚上11点到早上7点之间,每隔一小时
    0         11          4         *           mon-wed            date    test.sh # 每月的4号与每星期一至星期三的早上11点
    

crontab命令:

  • crontab file [-u user] 用指定的文件替代目前的crontab.
  • crontab -[-u user] 用標准輸入替代目前的crontab.
  • crontab -l[user] 列出用戶目前的crontab.
  • crontab -e[user] 編輯用戶目前的crontab.
  • crontab -d[user] 刪除用戶目前的crontab.
  • crontab -c dir 指定crontab的目錄
  • eg: 列出用戶目前的crontab
    > crontab -l
    10 6 * * * hello.sh
    40 10 01 * * java -jar InitContract.jar >/dev/null
    00 16 * * * /bin/ksh leave.sh > leave_update.log
    

示例:

  1. 编写shell,并赋予执行权限
    chmod +x file.sh
    # csh -x file.sh
    # ksh -x file.sh
    
  2. 导出现有crontab
    crontab -l > test_crontab
    
  3. 编辑导出的crontab文件,添加crontab任务
    vi test_crontab
    
  4. 导入新的crontab文件,使其生效
    crontab test_crontab
    

Shell

# 查看當前使用的Shell
> echo $SHELL
/bin/sh

# 查看当前shell的进程号
> echo $$
12282

# ps-A看自己shell的pid
> ps -A | grep 12282
12282 pts/19   0:00 sh

# 启动一个新的K Shell进程,用exit退出
> ksh
> exit

# 启动一个新的C Shell进程,用exit退出
> csh
> exit
  1. 命令回传值 $?

    • 若前一个命令运行的结果为正确,在 Linux 底下会回传一个 $? = 0 的值
    • cmd1 && cmd2
      • 若 cmd1 运行完毕且正确运行($?=0),则开始运行 cmd2
      • 若 cmd1 运行完毕且为错误 ($?≠0),则 cmd2 不运行
    • cmd1 || cmd2
      • 若 cmd1 运行完毕且正确运行($?=0),则 cmd2 不运行 + 若 cmd1 运行完毕且为错误 ($?≠0),则开始运行 cmd2
    • 示例:

      # 自动判断,如果没有该目录就给予创建
      ls /tmp/abc || mkdir /tmp/abc
      
      # 以 ls 测试 /tmp/vbirding 是否存在
      # 若存在则显示 "exist"
      # 若不存在,则显示 "not exist"
      ls /tmp/vbirding && echo "exist" || echo "not exist"
      
  2. exit n

    • n 是数字
    • 让程序中断,并回传一个数值给系统
    • 利用此功能,可以自订错误信息,并通过echo $?获取错误信息
  3. 变量

    • 变量的测试与内容替换

      变量配置方式 str 不存在 str 为空字符串 str 为非空字符串
      『判断』str是否存在 str不存在,返回expr str存在,返回str原值
      var=${str-expr} var=expr var= var=$str
      var=${str:-expr} var=expr var=expr var=$str
      『判断』str是否不存在 str不存在,返回空 |str存在,返回expr
      var=${str+expr} var= var=expr var=expr
      var=${str:+expr} var= var= var=expr
      使用等号 = str不存在,返回expr,且置str=expr str存在,返回str原值,str不变
      var=${str=expr} var=expr , str=expr var= ,str 不变 var=$str, str 不变
      var=${str:=expr} var=expr , str=expr var=expr, str=expr var=$str, str 不变
      使用? str不存在,expr 输出至 stderr str存在,返回str原值
      var=${str?expr} expr 输出至 stderr var= var=$str
      var=${str:?expr} expr 输出至 stderr expr 输出至stderr var=$str
    • 注意: 使用 : 则变量不存在或为空字符串则是一个效果
    • 打印变量

      > echo $var
      1
      
      # 扩展$var并添加串work
      # {} 把该变量从给它添加的字符里分离出来
      > echo ${var}work
      1work
      
  4. 日期date

     > date
     Tue Feb  7 15:35:15 CST 2012
     > echo `date +%y%m%d`
     120207
     > echo `date +%Y/%m/%d`
     2012/02/07
     > echo `date '+%H%M%S'`
     153255
     > echo `date +%D`
     02/07/12
     > echo `date +%h`
     Feb
     >  echo `date '+%Y/%m/%d %H:%M:%S'`
     2012/02/07 15:32:35
    
     date1=$(date --date='2 days ago' +%Y%m%d)  # 前两天的日期
     date2=$(date --date='1 days ago' +%Y%m%d)  # 前一天的日期
     date3=$(date +%Y%m%d)                      # 今天的日期
    
     # 配置档名
     file1=${filename}${date1}
     file2=${filename}${date2}
     file3=${filename}${date3}
    
  5. 命令替换:将命令放入反引号

     > set d = `date`    # 产生的值是一个数组
     > echo $d[1]
     Tue
    
     > set d="`date`"    # 输出封装在双引号里,所以是一个单串
     > echo $d[1]
     Tue Feb 7 13:33:06 CST 2012
     > echo $d[2]
     Subscript out of range
    
     > cal 2 2012
      February 2012
     S  M Tu  W Th  F  S
           1  2  3  4
     5  6  7  8  9 10 11
     12 13 14 15 16 17 18
     19 20 21 22 23 24 25
     26 27 28 29
     > echo Hello `cal 2 2012`        # 输出每个换行符都用一个空格代替
     Hello February 2012 S M Tu W Th F S 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
    

C Shell

  1. #!/bin/csh

  2. 用户接收 $<

    echo -n "What is your name? "    # -n 取消末尾的换行
    set name = $<
    
  3. 测试变量是否被设置 $?var

    • 1:设置了
    • 0:未设置
    • eg: echo $?hello
  4. 命令行变元$xxx

    $0,$1,$2,...
    $*
    $argv[0]
    $argv[1],$argv[2],...$argv[$#argv]
    $argv[*],$argv
    
  5. 数值运算

     > @ sum = 4 + 6
     > echo $sum
     10
    
     > @ sum ++
     > echo $sum
     11
    
     > @ sum += 3
     > echo $sum
     14
    
  6. 数组

    • (...) 创建数组
    • $#var 数组长度
    • $var[*] ,$var 打印所有元素
    • $var[..] 获取某个数组元素(数组从1~len)
    • shift var 数组左移一个元素

      > set name = "Hello GoodBye Sir"
      > echo $name[1]
      Hello GoodBye Sir
      > echo $name[2]
      Subscript out of range
      
      # 将变量封装在()中,创建一个叫做fruit的数组
      > set fruit = ($name)
      > echo $fruit
      Hello GoodBye Sir
      > echo $fruit[2]
      GoodBye
      
      # 创建数组
      > set fruit = ( app1 app2 app3 )
      > echo $fruit
      app1 app2 app3
      > echo $fruit[*]
      app1 app2 app3
      
      # 查询
      > echo $fruit[1]
      app1
      > echo $fruit[2-3]
      app2 app3
      > echo $#fruit
      3
      > echo $fruit[$#fruit]
      app3
      
      # 操作
      > set fruit[2] = bana
      > echo $fruit
      app1 bana app3
      
      > shift fruit
      > echo $fruit
      bana app3
      
  7. 条件表达式

    • ==,!=,>,>=,<,<=,~,!~,!,||,&&
      if ( $answer =~ [Yy]* ) then
      if ( $status == 0 ) then
      if ( $?prompt ) then
      if ( "$name" != "KK" ) then                #使用“”防止name中不止一个词而发生异常
      if ( ("$x" && "$y" ) || ! "$z" ) then            # ! 后面必须有一个空格
      
    • -r,-w,-x,-o
      if ( -r $file && -w $file ) then
      
    • -e,-z,-f,-d
      if ( ! -d $file ) then
      
  8. 条件判断

    • if/else if/else/endif
      if ( exp1 ) then
        echo "case1"
      else if ( exp2 ) then
        echo "case2"
      else if ( exp3 ) then
        echo "case3"
      else
        echo "case4"
      endif
      
    • switch/case/breaksw/endsw
      switch ( str )
      case red:
        echo "case1"
        breaksw
      case bl*:
        echo "case2"
        breaksw
      case [56].c:
        echo "case1"
        breaksw
      default:
        breaksw
      endsw
      
  9. 循环

    • foreach var (list) cmd end
        foreach person (`cat maillist`)
            echo $preson
        end
      
        foreach file (*.c)
            echo $file
        end
      
    • while(exp) cmd end
        while ( $num < 10 )
            echo $num
            @ num++
        end
      
        while ( "$answer" != "Bye" )
            set answer = $<
        end
      
        while ($#argv)
            echo $argv
            shift
        end
      
        while (1)
            cmd
            if () then
                break
            else if () then
                continue
            else
                cmd
            endif
        end
      
    • repeat n cmd
        repeat 3 echo hello
      

示例

  1. 设置变量

     set FTP_FTSERVER  = (10.7.49.15 10.7.49.17 10.7.49.152 10.7.54.2) 
     set ServletURL = http://10.7.33.16/cim/servlet
     set Rawdata = $downup\/$LOTNO-$CPNO
    
     set tdtplogfile = /home/klt/log/tdtp_1.`date '+%Y%m%d'`    
     set LOGS =  /db/data/autoftp/logs/pixart/`/usr/ucb/whoami`
    
     set tmpfile = /home/klt/wgetlog/$$
     set TEMPLASER = /home/cim1tdtp/temp/"$LLOTNO$WAFNUM"-$$.asc
    
     set lenOfPfile = `echo $proberfile | cut -d '/' -f8 | awk '{print length($1)}'`
     set lenOfWno   = `echo $proberfile | cut -d '/' -f8 | cut -d '.' -f1 | awk '{print length($1)}'`
     @ lenOfWno = $lenOfWno + 2
     set partlotno = `echo $proberfile | cut -d '/' -f8 | cut -c $lenOfWno-$lenOfPfile`
     echo partlotno is $partlotno
    
     set fproberfile = `ls /db/prober/map/$testgrp/$Rawdata/$partlotno=* | tail -1`      
     set fpfilelength = ` echo $fproberfile | awk '{print length($1)}'`
    
     set cpNo = `echo $configArr[1] | cut -c 3- `
     set USER_COUNTS = `who | grep klt | wc -l`
     set os = `uname`
     set RETURNVALUE=`echo $TMPLINE |awk -F\| '{print $1}'`
     set RemoteHost = `who am i |awk  '{print $NF}' | awk -F\( '{print $2}'  | awk -F\) '{print $1}' | awk -F. '{print $1}' `
    
  2. 接收用户输入

    • 存入一个变量
      echo CPNO:
      set CPNO = $<
      
    • 存入数组,小写转换为大写,获取字符串长度,设置变量

      echo   CPNO Flotno WaferNum PROBERIP TESTGROUP UP 
      set tempfile    = $<
      set file    = ($tempfile)
      
      if ( $#file == 6 ) then  
        set CPNO         = `echo $file[1] | tr "[:lower:]" "[:upper:]" `  
        set equip        = $file[4]
        set numchar      = ` echo $WAFERNUM | awk '{print length($1)}'`    
      endif
      
      if ( $numchar == 1 ) then
            set WAFERNUM = 0"$WAFERNUM"
      endif
      
  3. if 判断

     if (-e $tmpfile) then
         echo `date '+%H:%M:%S'` >> $tdtplogfile    
     endif
    
     if ( ! -d $LOGS ) then 
         mkdir -p $LOGS
     endif
    
     if ( ! -d $FTP_SRC_DIR ) then
         mkdir $FTP_SRC_DIR
         chmod 777 $FTP_SRC_DIR
     endif
    
     if ( $USER_COUNTS > 3 ) then 
         echo "Too Many User Execute TDTP manual(Default:3 users), Please wait..."
         echo "You can contact with user, and list as follows:"
         who | grep klt
         ps -ef | grep " klt "
         exit
     endif
    
     if ($os =~ [Ll][Ii][Nn][Uu][Xx]) then
         set wget = $srcpath"download-Linux"    
     else if ($os =~ [Ss][Uu][Nn][Oo][Ss]) then
         if ( `hostname` =~ [Jj]995*) then
             set wget = $srcpath"download-SunOS41"
         else
             set wget = $srcpath"download-SunOS" 
         endif
     endif
    
     if ($os !~ [Ll][Ii][Nn][Uu][Xx]) then
         unsetenv $PGM_WGETPATH
     endif
    
     # $status : 
     # grep 找到所寻找的模式 0; 找不到该模式 1; 找不到文件 2 ;
     # awk / sed 不论搜索的模式是否成功 0 ; 语法错误 非0
    
      grep "tw.com.kyec.cim.cp.task.TaskTDTPProber: true" $tmpfile  > &  /dev/null
       if ($status == 0 ) then
           echo TDTP have done $proberfile
       else 
          echo failed to do TDTP $proberfile
       endif
    
      set fproberfile = `ls /db/prober/map/$testertype/up/$templotno/$partlotno=* | tail -1`
      set fpfilelength = ` echo $fproberfile | awk '{print length($1)}'`
    
  4. foreach 循环

     foreach FTP_SERVER ( `echo $FTP_FTSERVER`)
         /usr/sbin/ping $FTP_SERVER | grep alive                 >& /dev/null
         if ( $status != 0 ) then
             echo Server can\'t connect to $FTP_SERVER           >> $FTP_LOG
             continue
         endif
     end
    
     set count = 1
     foreach filename (`cat $FileList`)
         set klotno = `echo $filename | cut -d'-' -f1`
         set barcode = `echo $filename | cut -d'_' -f1`
         set filetime = `echo $filename | cut -d'_' -f2 | cut -c 1-12`
    
         if ( $klotno == $lotno ) then
             set cmdStr = "$ServletURL/chkWfrStatus?CUST=ZKT&2DBARCODE=${barcode}&STNO=1&FILETIME=${filetime}&TESTER=E320_BDB01&HEAD=1"
             $WGET -q -O $tmpfile "$cmdStr"
             @ count++
         else
             echo "$klotno != $lotno" >> $logfile
         endif     
     end
    
  5. while 循环

     set waferno = 1
     while ( $waferno < 26 ) 
         @ waferno = $waferno + 1
         if ($waferno < 10 ) then
             continue
         endif
     end
    
     while ( $#argv > 0 )
         set args = "$args $argv[1]"
         shift argv
     end
    
  6. 压缩/解压缩

     unzip -o $FTP_AIM_DIR/$LOTNO/$TEMP_FILE -d $FTP_AIM_DIR/$LOTNO/
     unzip $TEMP_ZIP1.zip -d $TEMP_ZIP1.ZIP 
     uncompress < $FTP_AIM_DIR/$LOTNO/$TEMP_FILE | tar xf -
    
     tar -cvf $DirName".tar" $DirName
     compress $DirName".tar"
    
  7. 环境变量设置

     set srcpath = "/cim/pgm/prod/"
     setenv PGM_WGETPATH $srcpath
    
     setenv CIM_AUTO_INVOKED_PRCESS /home/asx/bin/auto_prober_klt.sh
     setenv CDC_PROBERD_LICENSE "O54k43jL7aI2LGaBo6bf6IxaLPQtc2"
    
  8. FTP

     # ftp -inv $FTP_SERVER
     echo user $FTP_USER $FTP_PASSWORD    >> $FTP_CMD_FILE
     echo cd /down                        >> $FTP_CMD_FILE
     echo bin                             >> $FTP_CMD_FILE            
     echo put $file                       >> $FTP_CMD_FILE
     echo bye                             >> $FTP_CMD_FILE
    
     ftp -inv $FTP_SERVER < $FTP_CMD_FILE
     echo "OK\!"
    
     echo user $FTP_USER $FTP_PASSWD           >   $FTP_CMD_FILE
     echo cd $FTP_DIR_A                        >>  $FTP_CMD_FILE
     echo bin                                  >>  $FTP_CMD_FILE
    
     echo "mget C*.TXT"                         >>  $FTP_CMD_FILE
     echo "mdir C*.TXT $DB_LOG"                 >>  $FTP_CMD_FILE 
     foreach TEMP_FILE ( C*.TXT )
         echo "del $TEMP_FILE"                  >>   $FTP_CMD_FILE 
     end
     ls *.zip | awk '{printf "del %s\n",$1}'     >>   $FTP_CMD_FILE    
     echo bye                                    >>  $FTP_CMD_FILE
    
     echo "## start get emap data from csmc ftp Server at `date` ##"  >>  $FTP_LOG
     (ftp -inv $FTP_SERVER < $FTP_CMD_FILE)       >>  $FTP_LOG
     echo "## end get emap data from csmc ftp Server at`date` ##"     >>  $FTP_LOG
    
  9. 特殊命令

     java -classpath .:/home/asx/proberlog/classes12.jar probLogScan $proberfile /home/asx/proberlog/  
     unix2dos   $LLOTNO$WAFNUM.asc     $LLOTNO$WAFNUM.asc
     exec /home/asx/bin/cdc_proberd > /home/asx/bin/cdc_screen.log.`date '+%Y%m%d'` 
     last | grep logged | grep tsk | grep $RemoteHost >& /dev/null 
     /home/asx/bin/auto_prober_real_klt.sh $1  $2 &
    
     sed -n 17,"$FILE_LENGTH"p $FILE > $tmpfile
     set CAT_X = `perl -e 'while(<>){$count+= s/X//g;} print "$count";' $tmpfile` 
    
     set lineSting =  `sed -n $line"p" $FILE_SHARE_TMP`
    
  10. 使用wget 触发 Servlet

    set WGET = /cim/bin/wget/ADVAN/wget
    $WGET -q -O $tmpfile  "$ServletURL/CpTrigger?TASK=$TASK"
    
  11. 调用java

    #! /bin/csh
    #classpath=.:$JAVA_HOME/lib/tools.jar:/home/cim1tdtp/oracle.jar
    set srcPath="/db/data/CGSPGM/exec"
    cd $srcPath
    echo `java ParseRawForCGS` >> insertResult.txt
    exit
    

K Shell

  1. #!/bin/ksh

  2. 读取用户输入read

     read                # $REPLY
     read answer
     print $answer
     read first middle last
     read -u3 name        # -u 从文件描述符中读取一行存储到变量name中
    
     while read -u3 line1 && read -u4 line2
     do
         print "$line1:$line2"
     done 3<$1 4<$2
    
  3. 只读 readonly

     > readonly name=Tom
     > print $name
     Tom
     > name=Joe
     ksh: name: is read only
    
  4. typeset 设置变量属性

    • -u 将变量值中所有字母全部转换成大写
    • -l 将变量值中所有字母全部转换成小写
    • -i 将变量值设为整数类型
    • -L width 在width宽度之内左对齐
    • -R width 在width宽度之内右对齐,前面空位用空格填充
    • -Z width 在width宽度之内右对齐
    • -x 设置一个全局变量。相当于 export
    • -r 设置一个变量具有只读属性,相当于readonly

      > typeset -i num        # 整数
      > typeset -i2 num        # 将数值num转换为二进制,i后面为进制数
      > print $num
      2#111
      
      > kk=5.6
      > typeset -i kk
      > echo $kk
      
  5. history

     history
     history -n            # print without line numbers
     history 8            # list form 8th command to present
     history -3            # list this command and  the 3 preceding it
     history -1 -5          # list last 5 commands,preceding this one in reversed order
     history -5 -1          # list last 5 commands,preceding this one in order
     history ls echo     # display from most recent "ls" command to most recent "echo" command
     history -r ls echo     # -r reverses the list
    
  6. r 重新执行命令

     r date
     r 3
     r vi
     r vi file1=file2
    
  7. 别名 alias

     alias c1='clear'
     alias l='ls -laF'
     unalias c1
     alias -t
    
  8. 命令行变元

     > set tom joe sam
     > echo $*
     tom joe sam
    
     > shift
     > echo $*
     joe sam
     > echo $#
     2
    
     > set $(date)
     > print $*
     Wed Feb 8 14:41:11 CST 2012
     > shift 3
     > print $*
     14:41:11 CST 2012
    
  9. 算数运算

     num=5
     let num=num+2        # (( num=num+2))
     print $num
    
  10. 数组

    • set -A var ... 创建数组
    • ${var[*]} 打印数组
    • ${var[..]} 获取数组某元素值
    > typeset -i names[4]
    > names[0]=30
    
    > set -A fruit apples pears bananana
    > print $fruit
    apples
    > print ${fruit[1]}
    pears
    
    > print ${fruit[*]}
    apples pears bananana
    > print ${#fruit[*]}  # 数组长度
    3
    
  11. 函数

    function funcName { cmd;}
    $funcName
    
    function funCName {print "Hi $1 and $2";)
    $funcName tom joe
    
    > typeset -f funCName                # list function define
    > typeset +f funCName                # list function name
    > unset -f funCName                  # clear funtion
    
  12. 条件判断

    • 整数测试: -eq,-ne,-gt,-ge,-lt,-le
    • 文件测试: -r,-w,-x,-d,-f, -s,-e,-a`
    • 逻辑操作符: &&,||,!
    • [] 等价于旧 test 命令 ([ 后面必须有空格)
    • [[]] / (()) 等价于新test 命令,允许使用Shell元字符扩展
      > name=Tom
      > test $name=Tome
      > [ $name = Tom ]
      > [[ $name = [Tt]?m ]]
      
  13. 判断

    • if/elif/else/fi
      if [[ ... ]]
      then
        cmd
      elif [[ ... ]]
        cmd
      else
        cmd
      fi
      
    • case/esac
      case var in
      value1)
        cmd
        ;;
      value2)
        cmd
        ;;
      *)
        cmd
        ;;
      esac
      
  14. 循环

    • for var in list do cmd done

        for person in `cat mylist`    # for person in $(<mylist)
        do
            print $person
        done
      

      -while [[expr]] do cmd done

        while (( num < 10 ))
        do
            print $num
            (( num=num+1))
        done
      
        while [[ $answer != "Tom" ]]
        do
            print "wrong!"
            read answer
        done
      
        cat $1 | while read line
        do
            print $line
      
        done > tmp$$
      
    • until [[expr]] do cmd done
        until who | grep linda
        do    
            sleep 5
        done
      
    • select
       select var in wordlist
       do
           cmd
       done
      
  15. IFS : shell 内部分隔符

    names=Tom:Dick:Sam:John
    OldIFS="$IFS"
    IFS=":"
    for person in $names
    do
        print Hi $preson
    done
    IFS="$OldIFS"
    

使用示例:

  1. 压缩备份资料(压缩文件夹)

     #!/bin/ksh
     read zipPath
     echo $zipPath
     cd     $zipPath
    
     # tar, compress
     for DirName in `ls `
     do
         tar -cvf $DirName".tar" $DirName
         compress $DirName".tar"
     done
    
     # zip
     for DirName in `ls `
         do
             echo $DirName
             zip -r $DirName".zip" $DirName
             rm -r $DirName
         done
    
     #collectData=$zipPath/1.txt
     #echo $collectData
     #while read DirName
     #do
     #        echo $DirName
     #        zip -r $DirName".zip" $DirName
     #        rm -r $DirName
     #done < $collectData
    
     echo OK
     exit
    
  2. If

     if [ ! -d $generatePath ]
     then
         mkdir $generatePath
     fi
    
     if [ -f $filePathWithName ]
     then
         if [[ $cpno -eq 1 ]] 
         then
             awk 'NR>21 {print $3" "$4" "$5" "$6" "$7" "$8}' $filePathWithName > $generatePath/$wafid
         else
             awk 'NR>21 {print $3" "$4" "$5" "$6" "$7}' $filePathWithName > $generatePath/$wafid
         fi
         echo "OK : $wafid " >> $resultLog
     else
         echo "FAIL : $count $filePathWithName unfound" >> $resultLog
         echo "FAIL : $count $filePathWithName unfound" >>$FailLog
     fi
    
     if [ $TEMPMAXNUM -lt 50 ]
     if [ $NUM -eq "0" ]
     if [ -f $FTP_SRC_DIR/$CUSTOMER/$FILE ]
     if [[ $LOCAL_SIZE == $REMOTE_SIZE ]]
    
     if [ -f $FTP_SRC_DIR/$CUSTOMER/$FYLE_TYPE/*H2T340* ]
     then
         if [ ! -d $FTP_SRC_DIR/$CUSTOMER/$FYLE_TYPE/stdfFilter ] 
         then
             mkdir $FTP_SRC_DIR/$CUSTOMER/$FYLE_TYPE/stdfFilter
         fi
         echo $FTP_SRC_DIR/$CUSTOMER/$FYLE_TYPE/*H2T340*
         mv $FTP_SRC_DIR/$CUSTOMER/$FYLE_TYPE/*H2T340* $FTP_SRC_DIR/$CUSTOMER/$FYLE_TYPE/stdfFilter/
         echo "move to stdfFilter ok"
     fi
    
  3. while

     count=1
     while read line
     do
        echo $count `date '+%m%d%H%M'` :$line    >> $resultLog
        filename=`echo $line | awk  '{print $6}'`
        generatePath=$resultPath/$klotNo
    
        let i=count%5 
        if [[ $i == 0 ]] 
        then
             echo "********************************************" >> $resultLog
             echo $count
        fi 
        let count=count+1 
     done < $collectData
    
     usedFilePathLength=1 
     while (( $usedFilePathLength < ${#arrayFileDir[*]}-1 ))  
     do
          echo mkdir ${arrayFileDir[$usedFilePathLength]} >> $FTP_CMD_FILE
          echo cd ${arrayFileDir[$usedFilePathLength]}    >> $FTP_CMD_FILE 
          cd ${arrayFileDir[$usedFilePathLength]} 
          let usedFilePathLength=usedFilePathLength+1
     done
    

B Shell

  1. #!/bin/bash

  2. read

    read -p "Please input your first name: " firstname  # 提示使用者输入
    read -p "Please input your last name:  " lastname   # 提示使用者输入
    echo -e "\nYour full name is: $firstname $lastname" # 结果输出
    
  3. 数值运算 ( bash shell 默认仅支持到整数的数据 )

    var=$((运算内容))
    echo $(( 13 % 3 ))
    

更多可参考:鸟哥的Linux私房菜

注意

shell脚本执行错误 $'\r':command not found

原因: 脚本是在window下编辑完成后上传到linux上执行的,win下的换行是回车符+换行符,也就是\r\n,而unix下是换行符\n。 linux下不识别\r为回车符,所以导致每行的配置都多了个\r,因此是脚本编码的问题。

解决方案: 在linux上执行 dos2unix 脚本名,再次执行脚本,报错消失

> dos2unix a.sh
> ./a.sh                # 或 sh a.sh