IO操作

命令汇总

0x00 read

参考文档:shell脚本之read命令

read命令是用来获取用户输入内容,即标准输入设备(键盘)输入内容,它是shell内建命令,使用help read命令可以查看其语法格式和使用说明,它的语法格式如下

read [-ers] [-a array] [-d delim] [-i text] [-n nchars] [-N nchars] [-p prompt] [-t timeout] [-u fd] [var_name ...]

其执行逻辑如下

  • read命令从标准输入设备中读取输入单行,默认单行的结束符号为回车换行符

    • 此处需要注意的是:不带任何选项的read命令,只有按下回车键才能结束read命令的读取
  • 然后将读取的单行根据IFS环境变量分裂成多个字段,并将分割后的字段分别赋值给read命令后面指定的变量列表var_name,其赋值逻辑如下

    • 第一个字段分配给第一个变量var_name1,第二个字段分配给第二个变量var_name2,依次到结束
    • 如果指定的变量名少于字段数量,则多出的字段数量也同样分配给最后一个var_name
    • 如果指定的变量命令多于字段数量,则多出的变量赋值为空
    • 如果没有指定任何var_name,则分割后的所有字段都存储在特定变量REPLY

read命令的常用选项有

  • -a:将分隔后的字段依次存储到-a指定的数组中,存储的起始位置从数组的index=0开始
  • -d:指定读取行的结束符号,默认结束符号为换行符
  • -n:限制读取N个字符就自动结束读取,如果没有读满N个字符就按下回车或遇到换行符,则也会结束读取
  • -N:严格要求读满N个字符才自动结束读取,即使中途按下了回车或遇到了换行符也不结束,其中换行符或回车算一个字符
  • -p:输出提示符或提示语,默认不支持\n换行,要换行需要特殊处理
  • -r:禁止反斜线的转义功能,这意味着\会变成文本的一部分
  • -s:静默模式,输入的内容不会回显在屏幕上,常用来获取密码输入
  • -t:给出超时时间,在达到超时时间时,read退出并返回错误,也就是说不会读取任何内容,即使已经输入了一部分

-a选项将读取的内容分配给数组变量,从索引号0开始分配

../../../_images/116.png

-d选项指定读取行的结束符号,而不再使用换行符

../../../_images/213.png

-n-N选项限制输入字符

../../../_images/312.png

-p选项输出提示字符串

../../../_images/413.png

-p选项默认不带换行功能,且也不支持\n换行,但通过$'string'的方式特殊处理,就可以实现换行的功能;关于$'String'$"String"的作用,详见shell中加引号有什么用

../../../_images/511.png

-s选项用来获取密码输入

../../../_images/612.png

-t选项给出输入时间限制,没完成的输入将被丢弃,所有变量将赋值为空(如果在执行read前,变量已被赋值,则此变量在read超时后将被覆盖为空)

../../../_images/75.png

read也可以用来在shell脚本中读取文件内容

# 每读取文件一行内容,就会进入一次while循环,直到读完文件尾部退出循环

# 读取文件方法一
while read line; do
        echo $line
done < /etc/passwd

# 读取文件方法二
exec </etc/passwd;while read line; do
echo $line
done

0x01 echo

echo命令类似于c中printf,用于标准输出,它是shell内建命令,使用help read命令可以查看其语法格式和使用说明,它的语法格式如下

echo [-neE] [arg ...]

它的执行逻辑是:将给定arg内容按照-neE选项指定的不同方式输出

echo命令常用的选项有

  • -n:取消分行输出
  • -e:支持字符串内转义字符的显示输出

关于echo命令的使用,主要关注一些几点

  • echo中的引号和感叹号:在bash环境中,感叹号只能通过单引号包围来输出,不能通过双引号来包围输出,原因有

    • 在bash环境中,感叹号表示引用历史命令,除非设置set +H关闭历史命令的引用
    • '':单引号表示强引用,该操作符的优先级大于!,即不会进行历史命令的引用,直接引用显示全部字符
    • "":双引号表示弱引用,该操作符的优先级小于!,即先进行历史命令的引用,然后再引用显示全部字符
../../../_images/83.png
../../../_images/93.png
  • echo中的转义:通过-e选项识别转义和特殊意义的符号,如换行符\n、制表符\t、转义符\
echo "hello world"   # 打印字符串

# -e选项支持字符串内转义字符的显示输出
echo -e "hello\bworld"        # 删除前面的字符,输出hellworld
echo -e "hello\tworld"        # 制表符,输出hello     world
echo -e "hello\vworld"        # 垂直制表符
echo -e "hello\nworld"        # 换行符
  • echo中的分行处理:默认情况下echo会在每行行尾加上换行符号,使用-n选项可以取消分行输出
../../../_images/101.png
  • echo中的颜色输出:echo可以控制字体颜色和背景颜色输出,因为需要使用特殊符号,所以需要配合-e选项来识别特殊符号

    • 常见的字体颜色:重置=0,黑色=30,红色=31,绿色=32,黄色=33,蓝色=34,紫色=35,天蓝色=36,白色=37

    • 常见的背景颜色:重置=0,黑色=40,红色=41,绿色=42,黄色=43,蓝色=44,紫色=45,天蓝色=46,白色=47

    • 字体控制选项:1表示高亮,4表示下划线,5表示闪烁

    • 着色显示字符串格式为:"\033[@;@mSTRING\033[0;0m"从左往右各字段的含义依次是

      • \033表示定义一个转义序列,也可以使用\e
      • [表示开始定义颜色
      • @;@表示颜色定义,第一个@表示字背景颜色,颜色范围40–47;;用来分隔字背景颜色和文字颜色;第二个@表示文字颜色,颜色范围30–37。如果没有相关定义则表示默认颜色
      • m表示颜色定义完毕
      • STRING表示要输出的字符串
      • \033表示定义一个转义序列,也可以使用\e
      • [表示再次开启颜色定义
      • 0;0m表示将前面定义的背景颜色和文字颜色重置为默认颜色;注意定义了颜色之后就需要使用此项来重置关闭颜色,否则会继续影响bash环境的颜色,前面定义了几个@,该处就应该使用几个0来重置对应的颜色
echo -e "\033[32mhello\033[0m"        # 着色显示,默认背景颜色,字颜色为32绿色
echo -e "\033[34m 蓝色字 \033[0m"
echo -e "\033[35m 紫色字 \033[0m"
echo -e "\033[36m 天蓝字 \033[0m"
echo -e "\033[37m 白色字 \033[0m"
echo -e "\033[40;37m 黑底白字 \033[0m"
echo -e "\033[41;37m 红底白字 \033[0m"
echo -e "\033[42;37m 绿底白字 \033[0m"
echo -e "\033[43;37m 黄底白字 \033[0m"
echo -e "\033[44;37m 蓝底白字 \033[0m"
echo -e "\033[45;37m 紫底白字 \033[0m"
echo -e "\033[46;37m 天蓝底白字 \033[0m"
echo -e "\033[47;30m 白底黑字 \033[0m"
echo -e "\033[41;37;0m 关闭所有属性 \033[0m"
echo -e "\033[41;37;1m 设置高亮度 \033[0m"
echo -e "\033[41;37;4m 下划线 \033[0m"
echo -e "\033[41;37;5m 闪烁 \033[0m"
echo -e "\033[41;37;7m 反显 \033[0m"
echo -e "\033[41;37;8m 消隐 \033[0m"
../../../_images/117.png
../../../_images/121.png

0x02 printf

使用printf命令可以输出比echo更规则更格式化的结果,它引用于C语言的printf函数,但是有些许区别;它也是shell内建命令,使用help printf命令可以查看其语法格式和使用说明,它的语法格式如下

printf [-v var] format [arguments]

其执行逻辑是:按照format定义的输出格式将arguments输出到指定位置;默认是输出到标准输出,如果使用了-v选项表示将arguments按照指定格式赋值给该选项指定的变量var

使用printf最需要注意以下两点

  • printf默认不在结尾加换行符,它不像echo一样,所以要手动加\n换号符
  • printf只是格式化输出,不会改变任何结果,所以在格式化浮点数的输出时,浮点数结果是不变的,仅仅只是改变了显示的结果

使用printf可以实现

  • 指定字符串的宽度
  • 实现左对齐(使用-)
  • 实现右对齐(默认值)
  • 格式化小数输出
#!/bin/bash

# 三个%分别对应后面的三个参数
# 减号"-"表示左对齐,默认表示右对齐
# 减号"-"后面的数字n表示占用n个字符
# 点号"."后面的数字m表示取小数点后m位
# s表示对应一个字符串变量
# f表示对应一个浮点数变量
# d表示对应一个整数变量
# \t表示制表符
# \n表示换行符
printf "%-s\t %-s\t %s\n" No Name Mark
printf "%-s\t %-s\t %4.2f\n" 1 Sarath 80.34
printf "%-s\t %-s\t %4.2f\n" 2 James 90.998
printf "%-s\t %-s\t %4.2f\n" 3 Jeff 77.564

# 执行结果如下
# No            Name            Mark
# 1             Sarath          80.34
# 2             James           91.00
# 3             Jeff            77.56