标准I/O

    它的参数如下。

    • -e 解释转义字符。
    • -n 不输出行尾的换行符
    1. $ echo "a\nb"
    2. a\nb
    3. $ echo -e "a\nb"
    4. a
    5. b

    上面代码中,如果不加-e参数,\n就会按字面形式输出;加了以后,就被解释成了换行符。

    引号之中可以包括多个换行符,即可以输出多行文本。

    1. echo "<HTML>
    2. <HEAD>
    3. <TITLE>Page Title</TITLE>
    4. </HEAD>
    5. <BODY>
    6. Page body.
    7. </BODY>
    8. </HTML>"

    echo ‘ Page body. ‘

    read

    read命令被用来从标准输入读取单行数据。这个命令可以用来读取键盘输入,当使用重定向的时候,读取文件中的一行数据。

    1. read [-options] [variable...]

    上面的 variable 用来存储输入数值的一个或多个变量名。如果没有提供变量名,shell 变量REPLY会包含数据行。

    基本上,read 会把来自标准输入的字段赋值给具体的变量。

    1. #!/bin/bash
    2. # read-multiple: read multiple values from keyboard
    3. echo -n "Enter one or more values > "
    4. read var1 var2 var3 var4 var5
    5. echo "var1 = '$var1'"
    6. echo "var2 = '$var2'"
    7. echo "var3 = '$var3'"
    8. echo "var4 = '$var4'"
    9. echo "var5 = '$var5'"

    上面脚本的用法如下。

    1. $ read-multiple
    2. Enter one or more values > a b c d e
    3. var1 = 'a'
    4. var2 = 'b'
    5. var3 = 'c'
    6. var4 = 'd'
    7. var5 = 'e'
    8. $ read-multiple
    9. Enter one or more values > a
    10. var1 = 'a'
    11. var2 = ''
    12. var3 = ''
    13. var5 = ''
    14. $ read-multiple
    15. Enter one or more values > a b c d e f g
    16. var1 = 'a'
    17. var2 = 'b'
    18. var3 = 'c'
    19. var4 = 'd'
    20. var5 = 'e f g'

    如果 read 命令接受到变量值数目少于期望的数字,那么额外的变量值为空,而多余的输入数据则会 被包含到最后一个变量中。

    如果 read 命令之后没有列出变量名,则一个 shell 变量REPLY,将会包含所有的输入。

    1. #!/bin/bash
    2. # read-single: read multiple values into default variable
    3. echo -n "Enter one or more values > "
    4. read
    5. echo "REPLY = '$REPLY'"

    上面脚本的输出结果如下。

    read命令的参数如下。

    • -a array 把输入赋值到数组 array 中,从索引号零开始。
    • -d delimiter 用字符串 delimiter 中的第一个字符指示输入结束,而不是一个换行符。
    • -e 使用 Readline 来处理输入。这使得与命令行相同的方式编辑输入。
    • -n num 读取 num 个输入字符,而不是整行。
    • -p prompt 为输入显示提示信息,使用字符串 prompt。
    • -r Raw mode. 不把反斜杠字符解释为转义字符。
    • -s Silent mode. 不会在屏幕上显示输入的字符。当输入密码和其它确认信息的时候,这会很有帮助。
    • -t seconds 超时. 几秒钟后终止输入。read 会返回一个非零退出状态,若输入超时。
    • -u fd 使用文件描述符 fd 中的输入,而不是标准输入。

    -p的例子。

    1. read -p "Enter one or more values > "
    2. echo "REPLY = '$REPLY'"

    -t-s的例子。

    1. if read -t 10 -sp "Enter secret pass phrase > " secret_pass; then
    2. echo -e "\nSecret pass phrase = '$secret_pass'"

    Shell的内部变量IFS可以控制输入字段的分离。例如,这个 /etc/passwd 文件包含的数据行 使用冒号作为字段分隔符。通过把 IFS 的值更改为单个冒号,我们可以使用 read 读取 /etc/passwd 中的内容,并成功地把字段分给不同的变量。

    1. #!/bin/bash
    2. # read-ifs: read fields from a file
    3. FILE=/etc/passwd
    4. read -p "Enter a user name > " user_name
    5. file_info=$(grep "^$user_name:" $FILE)
    6. if [ -n "$file_info" ]; then
    7. IFS=":" read user pw uid gid name home shell <<< "$file_info"
    8. echo "User = '$user'"
    9. echo "UID = '$uid'"
    10. echo "GID = '$gid'"
    11. echo "Full Name = '$name'"
    12. echo "Home Dir. = '$home'"
    13. else
    14. exit 1
    15. fi

    Shell 允许在一个命令之前立即发生一个或多个变量赋值。这些赋值为跟随着的命令更改环境变量。 这个赋值的影响是暂时的;只是在命令存在期间改变环境变量。

    虽然通常 read 命令接受标准输入,但是你不能这样做:

    我们期望这个命令能生效,但是它不能。这个命令将显示成功,但是 REPLY 变量 总是为空。为什么会这样?

    答案与 shell 处理管道线的方式有关系。在 bash(和其它 shells,例如 sh)中,管道线 会创建子 shell。它们是 shell 的副本,且用来执行命令的环境变量在管道线中。 上面示例中,read 命令将在子 shell 中执行。

    在类 Unix 的系统中,子 shell 执行的时候,会为进程创建父环境的副本。当进程结束 之后,环境副本就会被破坏掉。这意味着一个子 shell 永远不能改变父进程的环境。read 赋值变量, 然后会变为环境的一部分。在上面的例子中,read 在它的子 shell 环境中,把 foo 赋值给变量 REPLY, 但是当命令退出后,子 shell 和它的环境将被破坏掉,这样赋值的影响就会消失。

    使用 here 字符串是解决此问题的一种方法。

    1. #!/bin/bash
    2. # read-menu: a menu driven system information program
    3. clear
    4. echo "
    5. Please Select:
    6. 1. Display System Information
    7. 2. Display Disk Space
    8. 3. Display Home Space Utilization
    9. 0. Quit
    10. "
    11. read -p "Enter selection [0-3] > "
    12. if [[ $REPLY =~ ^[0-3]$ ]]; then
    13. if [[ $REPLY == 0 ]]; then
    14. echo "Program terminated."
    15. exit
    16. fi
    17. if [[ $REPLY == 1 ]]; then
    18. echo "Hostname: $HOSTNAME"
    19. uptime
    20. exit
    21. fi
    22. if [[ $REPLY == 2 ]]; then
    23. df -h
    24. exit
    25. fi
    26. if [[ $REPLY == 3 ]]; then
    27. if [[ $(id -u) -eq 0 ]]; then
    28. echo "Home Space Utilization (All Users)"
    29. du -sh /home/*
    30. else
    31. echo "Home Space Utilization ($USER)"
    32. du -sh $HOME
    33. fi
    34. exit
    35. fi
    36. else
    37. echo "Invalid entry." >&2