linux shell脚本攻略 第一章 小试牛刀 基本操作,变量,函数,管道等

目录

 

1.终端打印

1.1 实战

1.2 补充内容

2. 玩转变量

2.1 进程环境变量

2.2 常见变量使用

2.3 补充内容

3. 使用函数添加环境变量

4. shell数学计算

5. 文件描述符及重定向

5.1 重定向默认描述符

5.2 如何重定向

5.3 扩展方法

5.4 自定义文件描述符

6. 数组与关联数组

6.1 数组

6.2 关联数组(类似python中的字典)

7. 使用别名

8.日期和延时

9. 调试脚本

10. 函数和参数

11.管道:将命令序列的 输出读入变量

12. read命令

13. 运行命令直至成功

14.字段分隔符和迭代器

15. 比较与测试


1.终端打印

1.1 实战

  • 使用不带引号的echo,不能再文本中使用分号,因为分号在bash中被用作命令定界符
  • 变量替换在单引号中无效
  • 双引号中打印特殊字符需要加转义字符:
echo "hello world\!"
  • printf函数也可用于打印,类似于C语言
printf "s%" No

1.2 补充内容

  • echo -n 忽略行尾的换行符
  • echo -e 接收转义序列
ian@ian-virtual-machine:~$ echo "12\t3"
12\t3
ian@ian-virtual-machine:~$ echo -e "12\t3"
12	3
  • 使用转义序列可以打印彩色输出
echo -e "\e[1;42m Green Backgroud \e[0m"

输出:

2. 玩转变量

2.1 进程环境变量

查看进程运行时的环境变量可以用这个命令:

cat /proc/$PID/environ

输出:

USER=ianLC_TIME=zh_CN.UTF-8TEXTDOMAIN=im-configXDG_SEAT=seat0XDG_SESSION_TYPE=x11SSH_AGENT_PID=1628SHLVL=0QT4_IM_MODULE=ximHOME=/home/ianDESKTOP_SESSION=ubuntuGTK_MODULES=gail:atk-bridgeGNOME_SHELL_SESSION_MODE=ubuntuLC_MONETARY=zh_CN.UTF-8DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/busIM_CONFIG_PHASE=2LOGNAME=ianGTK_IM_MODULE=ibusUSERNAME=ianXDG_SESSION_ID=2WINDOWPATH=2PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/binLC_ADDRESS=zh_CN.UTF-8XDG_RUNTIME_DIR=/run/user/1000DISPLAY=:0LANG=en_US.UTF-8XDG_CURRENT_DESKTOP=ubuntu:GNOMELC_TELEPHONE=zh_CN.UTF-8XDG_SESSION_DESKTOP=ubuntuXMODIFIERS=@im=ibusXAUTHORITY=/run/user/1000/gdm/XauthoritySSH_AUTH_SOCK=/run/user/1000/keyring/sshLC_NAME=zh_CN.UTF-8SHELL=/bin/bashQT_ACCESSIBILITY=1GDMSESSION=ubuntuLC_MEASUREMENT=zh_CN.UTF-8TEXTDOMAINDIR=/usr/share/locale/GPG_AGENT_INFO=/run/user/1000/gnupg/S.gpg-agent:0:1LC_IDENTIFICATION=zh_CN.UTF-8XDG_VTNR=2QT_IM_MODULE=ximPWD=/home/ianCLUTTER_IM_MODULE=ximXDG_DATA_DIRS=/usr/share/ubuntu:/usr/local/share:/usr/share:/var/lib/snapd/desktopXDG_CONFIG_DIRS=/etc/xdg/xdg-ubuntu:/etc/xdgLC_NUMERIC=zh_CN.UTF-8LC_PAPER=zh_CN.UTF-8GNOME_DESKTOP_SESSION_ID=this-is-deprecatedXDG_MENU_PREFIX=gnome-SESSION_MANAGER=local/ian-virtual-machine:@/tmp/.ICE-unix/1533,unix/ian-virtual-machine:/tmp/.ICE-unix/1533DESKTOP_AUTOSTART_ID=10692a68641ba1de1158631729595816000000015330000GIO_LAUNCHED_DESKTOP_FILE=/usr/share/applications/org.gnome.Shell.desktopGIO_LAUNCHED_DESKTOP_FILE_PID=1

2.2 常见变量使用

  • 变量赋值方法:var=value, var = value的写法是错的
  • 可以在printf或者echo的双引号中引用变量
  • 单引号不会被扩展,会按照原样式显示
ian@ian-virtual-machine:~$ echo $a
1
ian@ian-virtual-machine:~$ echo '$a'
$a

2.3 补充内容

  • 获取字符串长度:${#var}
ian@ian-virtual-machine:~$ echo ${#a}
1
  • 识别当前使用shell:echo $0 或者 echo $SHELL
  • 检测是否为超级用户:echo $UID,返回值为0则为root
  • 修改bash提示符:设置PS1变量,例如,PS1="Ian>"
    ian@ian-virtual-machine:~$ PS1="Ian>"
    Ian>
    

    3. 使用函数添加环境变量

当需要经常安装软件,将路径加入到path中时,可以在bashr中添加一个添加路径的函数。

比如常见的加入path的命令为:

export PATH=/home/ian:$PATH
echo $PATH
/home/ian:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin

加入bashrc的函数:

prepend() { [ -d "$2" ] && eval $1=\"$2':'\$$1\" && export $1; }

函数先检查第二个参数是否存在,如果存在

调用方法:

Ian>echo $PATH
/home/ian:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
Ian>prepend PATH /home/ian/Videos/
Ian>echo $PATH
/home/ian/Videos/:/home/ian:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin

4. shell数学计算

可以使用let,(()),和[]执行基本的算术操作,expr和bc可以用于高级操作

  • 基本运算
    Ian>a=4
    Ian>b=5
    Ian>let result=a+b
    Ian>echo $result
    9
    Ian>result=$[ a + b ]
    Ian>echo $result
    9
    Ian>result=$(( a + 5))
    Ian>echo $result
    9
    Ian>result=$(expr $a + 5)
    Ian>echo $result
    9
    

    不过,(())的写法在一些编程标准中是不允许的。基础运算只支持整数,不支持浮点数

  • bc可以进行浮点计算和高级函数的计算

    Ian>echo "$a * 0.56"|bc
    2.24
    Ian>echo "sqrt(100)" |bc
    10

    5. 文件描述符及重定向

5.1 重定向默认描述符

系统保留的文件描述符:

  • 0:stdin(标准输入)
  • 1:stdout(标准输出)
  • 2:stderr(标准错误)

5.2 如何重定向

使用>或者>>可以将标准输出重定向。

将标准错误重定向到文件:

Ian>ls + 2>a.log
Ian>cat a.log 
ls: cannot access '+': No such file or directory

可以将标准输出和标准错误重定向到不同的文件:

ls + 2>a.log 1>b.log

将stderr转换成stdout之后重定向到一个文件:

ls + >a.log 2>&1 
ls + >/dev/null 2>&1 #不输出任何信息

关于2>&1的含义可见

https://blog.csdn.net/sc9018181134/article/details/88432070

 

5.3 扩展方法

tee命令既可以将stdin中的数据重定向到文件,还可以提供一份重定向数据的副本作为后续的stdin(主要用于将标准输出重定向到文件中)

Ian>cat *.log *.lsodfj|tee a.out|cat -n
cat: '*.lsodfj': No such file or directory
     1	ls: cannot access '+': No such file or directory
     2	blog file
Ian>cat a.out 
ls: cannot access '+': No such file or directory
blog file

当只需获取上一个命令的输出,而不需要输出到文件时,可以用tee -

Ian>echo who is this|tee -|cat -n
     1	who is this

5.4 自定义文件描述符

文件描述符是一种用于访问文件的抽象指示器。具体解释:https://www.cnblogs.com/alan666/p/8311890.html

可以使用exec创建自定义的文件描述符;

Ian>touch input.txt
Ian>exec 3<input.txt
Ian>echo test input line >input.txt 
Ian>cat <&3
test input line

如果需要再次读取就需要重新用exec分配。

6. 数组与关联数组

6.1 数组

  • 定义数组
    Ian>a=(1 2 3 4 5)
    Ian>b[1]=1
    

     

  • 打印数组
Ian>echo ${a[*]}
1 2 3 4 5
Ian>echo ${b[*]}
5 1
Ian>echo ${a[0]}
1

6.2 关联数组(类似python中的字典)

  • 定义关联数组,赋值关联数组,显示关联数组:
    Ian>declare -A ass_a
    Ian>ass_a=([index1]=val1 [index2]=val2)
    Ian>ass_a[index3]=val3
    Ian>echo ${ass_a[*]}
    val1 val2 val3
    Ian>echo ${ass_a[index1]}
    val1
    

     

  • 列出数组索引(key值)
Ian>echo ${!ass_a[*]}
index1 index2 index3

 7. 使用别名

  • alias创建,删除别名
    Ian>alias hls='hadoop fs -ls'
    Ian>hls
    hadoop: command not found
    Ian>alias hls=
    Ian>hls
    Ian>
    
  • 忽略别名使用,在命令之前加反斜杠'\'进行转义
    Ian>alias hls1='hadoop fs -ls'
    Ian>\hls1
    
    Command 'hls1' not found, did you mean:
    
      command 'hls' from deb hfsutils
    
    Try: sudo apt install <deb name>
    
    

     

8.日期和延时

  • 读取,设置日期和时间:
Ian>date   #获取日期
Thu Apr  9 21:15:35 CST 2020
Ian>date +%s #获取时间戳
1586438156
Ian>date --date "Thu Apr  9 21:15:35 CST 2020" +%s #将日期转换为时间戳
1586438135
Ian>date --date "Thu Apr  9 21:15:35 CST 2020" +%A #将日期按照星期打印
Thursday
  • 格式串+可以作为date的参数,按照相应格式打印出日期,比如:
    Ian>date +%A
    Thursday
    Ian>date "+%d %B %Y"
    09 April 2020
    
  •  日期格式列表如下:

    日期:

    %a : 星期几 (Sun..Sat) 
    %A : 星期几 (Sunday..Saturday) 
    %b : 月份 (Jan..Dec) 
    %B : 月份 (January..December) 
    %c : 直接显示日期和时间 
    %d : 日 (01..31) 
    %D : 直接显示日期 (mm/dd/yy) 
    %h : 同 %b 
    %j : 一年中的第几天 (001..366) 
    %m : 月份 (01..12) 
    %U : 一年中的第几周 (00..53) (以 Sunday 为一周的第一天的情形) 
    %w : 一周中的第几天 (0..6) 
    %W : 一年中的第几周 (00..53) (以 Monday 为一周的第一天的情形) 
    %x : 直接显示日期 (mm/dd/yy) 
    %y : 年份的最后两位数字 (00.99) 
    %Y : 完整年份 (0000..9999) 

    时间:

    % : 印出冒号
    % %n : 下一行 
    %t : 跳格 
    %H : 小时(00..23) 
    %I : 小时(01..12) 
    %k : 小时(0..23) 
    %l : 小时(1..12) 
    %M : 分钟(00..59) 
    %p : 显示本地 AM 或 PM 
    %r : 直接显示时间 (12 小时制,格式为 hh:mm:ss [AP]M) 
    %s : 从 1970 年 1 月 1 日 00:00:00 UTC 到目前为止的秒数 %S : 秒(00..61) 
    %T : 直接显示时间 (24 小时制) 
    %X : 相当于 %H:%M:%S 
    %Z : 显示时区 

9. 调试脚本

  • bash -x

bash -x命令可以打印出所执行的每一行命令及当前的状态。例如新建一个脚本:

#!/bin/bash
#script.sh
for i in 1 2 3;
do
    echo $i
done
echo "done"

 

使用bash -x 命令:

Ian>bash -x script.sh 
+ for i in 1 2 3
+ echo 1
1
+ for i in 1 2 3
+ echo 2
2
+ for i in 1 2 3
+ echo 3
3
+ echo done
done
  • set -x和set +x

这两个命令可以设置在脚本的中间,只调试部分脚本(但是在Bash4.1.10后就不好使了):

修改script脚本:

#!/bin/bash
for i in 1 2 3;
do
    set -x
    echo $i
    set +x   
done
echo "done script"

输出: 

Ian>bash script.sh 
+ echo 1
1
+ set +x
+ echo 2
2
+ set +x
+ echo 3
3
+ set +x
done script
  • 自定义显示调试信息:调用_DEBUG参数。修改脚本如下:
    #!/bin/bash
    #script.sh
    function DEBUG()
    {
        [ "_DEBUG" == "on" ] && $@ || echo "debug"
    }
    for i in 1 2 3;
    do
        DEBUG echo $i   
    done
    echo "done script"

    调用:

    Ian>bash script.sh 
    debug
    debug
    debug
    done script
    

     

  • 使用shebang调试:可将#!/bin/bash修改成为#!/bin/bash -xv

10. 函数和参数

  • 定义函数
    #!/bin/bash
    function fname1()
    {
            echo 1;
    }
    fname2()
    {
            echo 2;
    }
    fname3()
    {
            echo $1;
    }
    fname1
    fname2
    fname3 3

    输出:

    Ian>bash func.sh 
    1
    2
    3
    

     

  • 导出函数:可以像环境变量一样导出函数。
export -f fname1

在原先的脚本中加入一行,然后source脚本,就可以调用函数:

Ian>source func.sh 
1
2
3
Ian>fname1
1
  • 读取命令返回值:$?
    Ian>ls
    func.sh  script.sh
    Ian>echo $?
    0
    
     

11.管道:将命令序列的 输出读入变量

  • 管道使用
ls | cat -n > out.txt

将ls的结果传入给cat -n

  • 获取管道相连的命令序列的输出:$(cmd)
Ian>a=`ls | cat -n`
Ian>echo $a
1 func.sh 2 out.txt 3 script.sh
Ian>b=$(ls | cat -n)
Ian>echo $b
1 func.sh 2 out.txt 3 script.sh
  • 定义一个子进程

命令在子进程执行,对当前任务没有任何影响:

#脚本
#!/bin/bash
pwd
(cd /home; pwd; ls)
pwd

#调用
Ian>sh prp.sh 
/home/ian/test
/home
ian
/home/ian/test

12. read命令

read用于从键盘或者标准输入中读取文本。

  • 从输入中读取n个字符:read -n 2 var
Ian>vim prp.sh 
Ian>read -n 2 var
hiIan>echo $var
hi
  • 无回显方式读取:read -s
  • 显示提示信息读取:read -p "input:" var
  • 特定时限内读取:read -t 10 var
  • 用特殊的定界符作为输入行的结束:read -d ":" var
Ian>read -d ":" var
fdashfhas
fnaihfo
fjap'ja:Ian>echo $var
fdashfhas fnaihfo fjap'ja

13. 运行命令直至成功

  • 定义一个repeat函数
repeat()
{
    while true;
    do
        $@ && return
    done
}

函数定义了一个while循环,如果传入函数返回为true,则返回,否则一直执行.

也可以用":"代替true

14.字段分隔符和迭代器

  • 内部字段分隔符(IFS)设置当前文本的分隔符(默认为空格)。
Ian>echo $IFS

Ian>data="1,2,3"
Ian>for item in $data;do echo item:$item; done
item:1,2,3
Ian>IFS=,
Ian>for item in $data;do echo item:$item; done
item:1
item:2
item:3
  • shell中生成数字或者字母列表
Ian>echo {1..3}
1 2 3
Ian>echo {a..e}
a b c d e

15. 比较与测试

  • if 可以用于测试:
Ian>if true; then echo 1; fi
1
Ian>if false; then echo 1; elif true; then echo 2; else echo 3; fi
2
  • 算数比较

注意在[]与操作符之间需要有一个空格,不然会报错

Ian>if [ $var -eq 0 ]; then echo 0; else echo 1; fi
0

-gt:大于

-lt:小于

-ge:大于等于

-le:小于等于

-a:逻辑与

-o:逻辑或

  • 文件系统相关测试
-e filename 如果 filename存在,则为真 
-d filename 如果 filename为目录,则为真 
-f filename 如果 filename为常规文件,则为真 
-L filename 如果 filename为符号链接,则为真 
-r filename 如果 filename可读,则为真 
-w filename 如果 filename可写,则为真 
-x filename 如果 filename可执行,则为真 
-s filename 如果文件长度不为0,则为真 
-h filename 如果文件是软链接,则为真
  • 字符串比较

[[ $str1 == $str2 ]]

>,=,!=,-z(空字符串),-n(非空字符串)

  • 逻辑运算

&&,||

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值