Linux Shell脚本攻略读书笔记(1)

以下的例子都以bash为环境,别的shell可能不能用

  1. 基本知识

    命令提示符,$表示普通用户,#表示管理员用户root
    
    ~/.bash_history 保存用户运行过的命令
    
    ~/.bashrc 定义诸如提示文本、颜色等各类设置,启动shell时,会执行这组命令。登录shell则是~/.bash_profile
    
    登录shell是登录主机后获得的那个shell。如果登录图形界面环境(比如 GNOME、KDE等)后打开了一个shell,就不是登录shell
    
  2. 终端打印

    echo时,双引号中的!需要进行转义,但是单引号和直接跟在echo后面不用转义(比如 echo hello !)
    
    使用不带引号的echo时,没法在所要显示的文本中使用分号
    
    变量替换在单引号中无效
    
    printf需要自己添加换行,可以跟格式,比如printf  "%-5s %-10s %-4.2f\n" 1 Sarath 80.3456,横杠表示左对齐,不指定时采用右对齐
    
    echo可以用-n来忽略结尾的换行,可以用-e和双引号来接收转义序列字符串,比如echo -e "1\t2\t3"
    
    颜色有对应的编码,重置=0,黑色=30,红色=31,绿色=32,黄色=33,蓝 色=34,洋红=35,青色=36,白色=37,比如echo -e "\e[1;31m This is red text \e[0m",\e定义一个转义序列,[表示开始定义颜色,分号前为前景色,分号后为背景色,m表示颜色定义完毕
    
    背景色的编码,重置=0,黑色=40,红色=41,绿色=42,黄色=43,蓝色=44,洋红=45,青色=46,白色=47,比如echo -e "\e[1;42m Green Background \e[0m"
    
  3. 变量和环境变量

    env查看终端的环境变量,cat /proc/$PID/environ来查看PID对应的进程的环境变量,比如cat /proc/2277/environ,测试发现无效
    
    tr '\0' '\n'替换操作,将\0替换为\n,比如cat file | tr "abc" "xyz" > new_file
    
    var=value是赋值操作,var = value是相等操作,差别就是两个空格
    
    echo "We have $count ${fruit}(s)" 引用变量$或者${}都可以
    
    PATH通常定义在/etc/environment或/etc/profile或~/.bashrc 中,给PATH添加路径可以用export PATH="$PATH:/home/user/bin",export用于设置变量,冒号用于分隔
    
    一些常用的环境变量HOME、PWD、USER、UID、SHELL
    
    获取变量值的长度,length=${#var}
    
    root用户的UID是0
    
    \u可以扩展为用户名,\h可以扩展为主机名,而\w可以扩展为当前工作目录,试了下好像不行,可能使用姿势不对
    
  4. 文件比较运算符

    -e filename 如果 filename存在,则为真 [ -e /var/log/syslog ]
    -d filename 如果 filename为目录,则为真 [ -d /tmp/mydir ]
    -f filename 如果 filename为常规文件,则为真 [ -f /usr/bin/grep ]
    -L filename 如果 filename为符号链接,则为真 [ -L /usr/bin/grep ]
    -r filename 如果 filename可读,则为真 [ -r /var/log/syslog ]
    -w filename 如果 filename可写,则为真 [ -w /var/mytmp.txt ]
    -x filename 如果 filename可执行,则为真 [ -x /usr/bin/grep ]
    
    filename1 -nt filename2 如果 filename1比 filename2新,则为真
    filename1 -ot filename2 如果 filename1比 filename2旧,则为真
    
  5. 数学运算

    let命令可以直接执行基本的算术操作。当使用let时,变量名之前不需要再添加$
    no1=4;
    no2=5;
    let result=no1+no2 # 直接这样result=no1+no2会打印no1+no2,而$result=no1+no2是个语法错误
    echo $result
    
    操作符[]的使用方法和let命令类似
    result=$[ no1 + no2 ]
    也可以使用$前缀
    result=$[ $no1 + 5 ]
    
    使用(())时,变量名之前需要加上$;expr同样可以用于基本算术操作
    result=$(( no1 + 50 ))
    
    result=`expr 3 + 4`
    result=$(expr $no1 + 5)
    
    以上这些方法只能用于整数运算,而不支持浮点数
    
    可以用bc来执行一些浮点运算,单独使用会出现交互模式
    echo "4 * 0.56" | bc
    
    no=54;
    echo "$no * 1.5" | bc
    
    设置小数位数
    echo "scale=4;3/8" | bc
    
    ibase用于设置输入数据的进制
    obase用于输出的数据进制
    echo "obase=2;100" | bc // 输出1100100
    echo "ibase=2;100" | bc // 输出4
    
    平方和平方根
    echo "sqrt(100)" | bc 
    echo "10^10" | bc 
    
  6. 文件描述符

    0 stdin(标准输入)
    1 stdout(标准输出)
    2 stderr(标准错误)
    
    以上都有对应的设备文件,/dev/stdin、/dev/stdout、/dev/stderr
    
    最常见的文件输入方式
    输入时会先清空文件内容
    echo "This is a sample text 1" > temp.txt
    
    追加内容
    echo "This is sample text 2" >> temp.txt
    
    当一个命令发生错误并退回时,会返回一个非0的退出状态;当命令成功完成后,会返回数字0。退出状态可以从特殊变量$?中获得(在命令执行之后立刻运行echo $? 就可以打印出退出状态
    
    将标准输入输出重定向
    cmd 2>stderr.txt 1>stdout.txt
    
    将stderr转换成stdout,stderr和stdout都被重定向到同一个文件中
    cmd 2>&1 output.txt
    同上
    cmd &> output.txt
    
    只看看命令是否执行正确而不想看任何输出(把标准输入指向了/dev/null)
    cat $filename >/dev/null
    
    /dev/null,或称空设备,是一个特殊的设备文件,它丢弃一切写入其中的数据(但报告写入操作成功),读取它则会立即得到一个EOF
    
    删除文件内容而不删除文件本身
    cat /dev/null > /var/log/messages
    
    有同样的效果,但不会产生新的进程
    : > /var/log/messages
    
    tee命令用于读取标准输入的数据,并将其内容输出成文件,默认情况下,tee命令会将文件覆盖,-a选项,用于追加内容。tee不读取stderr的内容
    command | tee FILE1 FILE2
    
    重定向操作符(>、>>),使用特定的文件描述符,必须将描述符编号置于操作符之前
    >等同于1>
    >>等同于1>>
    
    打开交互模式,读取输入,直到输入EOF,停止,然后加入到test.sh
    cat << EOF > test.sh
    cat << EOF >> test.sh
    
    读取test1.sh文件的内容,并追加到testShell
    cat < test1.sh >> testShell
    
    不要玩这个,会死循环(?)
    cat < testShell >> testShell
    
    自定义文件描述符
    创建读取
    exec 3<testShell
    读取,只能读取一次
    cat<&3
    
    创建写入
    exec 4>output.txt
    写入,可以多次执行,而且后面内容会追加
    echo newline >&4
    
    创建追加
    exec 5>>input.txt
    追加,可以多次执行,后面内容会追加
    echo appended line >&5
    
  7. 数组和关联数组

    假设array_var是一个数组,打印array_var的值
    echo ${array_var[*]}
    或
    echo ${array_var[@]}
    
    打印某个索引对应的值
    echo ${array_var[0]}
    
    index=5
    echo ${array_var[$index]}
    
    打印长度
    echo ${#array_var[*]}
    
    关联数组
    先声明
    declare -A fruits_value
    
    赋值
    fruits_value=([index1]=val1 [index2]=val2)
    或
    fruits_value[index1]=val1
    fruits_value[index2]=val2
    
    打印索引
    echo ${!fruits_value[*]}
    或
    echo ${!fruits_value[@]}
    
  8. 别名

    alias install='sudo apt-get install'
    
    写入bashrc
    echo 'alias cmd="command seq"' >> ~/.bashrc
    
    取消别名
    unalias
    或
    alias example= #等号后面啥都没有
    
    删除前备份文件
    alias rm='cp $@ ~/backup && rm $@'
    
    $@ 表示全部参数
    $# 表示参数长度
    
    忽略别名,\command,比如\cp,可以防止攻击或者误用
    
  9. 获取终端信息

    获取终端的行数和列数
    tput cols
    tput lines
    
    打印出当前终端名
    tput longname
    
    将光标移动到坐标(100,100)处
    tput cup 100 100
    
    设置终端背景色
    tput setb n
    其中n可以在0到7之间取值
    
    设置文本前景色
    tput setf n
    其中n可以在0到7之间取值
    
    设置文本样式为粗体
    tput bold
    
    设置下划线的起止
    tput smul
    tput rmul
    
    删除从当前光标位置到行尾的所有内容
    tput ed
    
    #!/bin/sh
    #Filename: password.sh
    echo -e "Enter password: "
    stty -echo
    read password
    stty echo
    echo
    echo Password
    
    stty选项-echo禁止将输出发送到终端,选项echo允许发送输出
    read 命令被用来从标准输入读取单行数据。这个命令可以用来读取键盘输入,当使用重定向的时候,可以读取文件中的一行数据
    
  10. 日期和延时

    读取日期
    date
    
    UTC时间,单位:秒
    date +%s
    
    格式转换
    date --date "Thu Nov 18 08:07:21 IST 2010" +%s
    
    获取星期几
    date --date "Jan 20 2001" +%A
    
    查看命令statements所花的时间
    start=$(date +%s)
    statements;
    end=$(date +%s)
    difference=$(( end - start))
    echo Time taken to execute commands is $difference seconds.
    
    循环输出1到5
    #!/bin/bash
    echo -n Count: 
    tput sc #存储光标位置
    count=0;
    while true;
    do
        if [ $count -lt 5 ];
        then
            let count++;
            sleep 1;
            tput rc #恢复光标位置
            tput ed #清除从当前光标位置到行尾之间的所有内容
            echo -n $count;
        else exit 0;
    fi done
    
  11. 调试

    打印当前在执行的命令
    bash -x script.sh
    
    打印出位于-x和+x之间的代码
    for i in {1..6}; 
    do
      set -x
      echo $i
      set +x
    done
    echo "Script executed"
    
    
  12. 函数

    fname() {
      echo $1, $2; #访问参数1和参数2,$0代表当前脚本的文件名
      echo "$@"; #以列表的方式一次性打印所有参数 
      echo "$*"; #类似于$@,但是参数被作为单个实体 
      return 0; #返回值
    }
    
    函数导出
    export -f fname
    
    获取函数或者命令的返回值,$?
    cmd; 
    echo $?;
    
  13. 将命令的输出读入变量

    子shell
    cmd_output=$(ls | cat -n)
    echo $cmd_output
    
    反引用
    cmd_output=`ls | cat -n`
    echo $cmd_output
    
    用()生成子shell,子shell执行不影响当前shell
    pwd;
    (cd /bin; ls);
    pwd;
    
    使用子shell或反引用的方法将命令的输出读入一个变量中,可以将它放入双引号中,以保留空格和换行符
    如果text.txt是一个包含空格和换行的文本,这种方式会丢失内容
    out=$(cat text.txt)
    echo $out
    
    这种就不会
    out="$(cat tex.txt)"
    echo $out
    
  14. 不使用回车读取 n个字符

    把输入截取2个字符,并保存到变量var里,输入的时候就会被截断
    read -n 2 var
    
    无回显输入
    read -s var
    
    限制输入的时间,单位秒
    read -t timeout var
    
    设置结束标记为冒号
    read -d ":" var
    
  15. 运行命令直至成功

    在大多数现代系统中,true是作为/bin中的一个二进制文件来实现的,每执行一 次while循环,shell就生成一个进程
    repeat() {
      while true 
      do
        $@ && return
      done
    }
    
    冒号总是返回为0的退出码,和true的效果一样,并且不会生成多个进程
    repeat() { while :; do $@ && return; done }
    
    重复执行期间延时30s
    repeat() { while :; do $@ && return; sleep 30; done }
    
  16. 字段分隔符和迭代器

    IFS内部字段分隔符
    data="name,sex,rollno,location"
    oldIFS=$IFS
        IFS=,
        for item in $data;
        do
            echo Item: $item
        done
    IFS=$oldIFS
    
    循环的写法
    for var in list
    do 
    	commands; 使用变量$var
    done
    
    另一种
    for((i=0;i<10;i++))
    {
    	commands; #使用变量$i
    }
    
    while循环
    while condition
    do
    	commands;
    done
    
    until循环
    x=0;
    until [ $x -eq 9 ]; #条件是[$x -eq 9 ] 
    do
    	let x++;
    	echo $x;
    done
    
    生成1到50的一种简单写法
    {1..50}
    
    
  17. 比较与测试

    if condition;
    then
    	commands;
    else if condition; 
    then
    	commands;
    else
    	commands; 
    fi
    
    [ condition ] && action; # 如果condition为真,则执行action
    [ condition ] || action; # 如果condition为假,则执行action
    
    [ $var1 -ne 0 -a $var2 -gt 2 ] #使用逻辑与-a,这里不能用&&和||,&&和||用于将多个条件组合起来
    [ $var1 -ne 0 -o var2 -gt 2 ] #逻辑或 -o
    
    检查字符串要用两个中括号
    [[ $str1 = $str2 ]]
    [[ $str1 != $str2 ]]
    [[ -z $str1 ]]:如果str1包含的是空字符串,则返回真
    [[ -n $str1 ]]:如果str1包含的是非空字符串,则返回真
    
    test命令
    if  [ $var -eq 0 ]; then echo "True"; fi
    可以写成:
    if  test $var -eq 0 ; then echo "True"; fi
    

这还只是第一章,内容有点多。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值