搞定。让我们再来运行一次看看:
  [root@localhost ~]
  # ./note.sh
  Phone number?
  556
  Name?
  Janine
  Issue?
  Mouse was broken.
  [root@localhost ~]
  # cat data.txt
  987/Jimmy/Keybord issue.
  556/Janine/Mouse was broken.
  [root@localhost ~]
  #
  我们的文件在增长,让我们在每行前面加个日期吧,这对于今后摆弄这些统计数据时会很有用。要实现这功能,我们可以使用date命令,并指定某种格式,因为我不喜欢默认格式:
  [root@localhost ~]
  # date
  Thu Apr 23 21:33:14 EEST 2015 <---- date命令的默认输出
  [root@localhost ~]
  # date "+%Y.%m.%d %H:%M:%S"
  2015.04.23 21:33:18 <---- 格式化后的输出
  有几种方式可以读取命令的输出到变量,在这种简单的情况下,我们将使用`(是反引号,不是单引号,和波浪号~在同一个键位):
  [root@localhost ~]
  # cat note.sh
  #!/bin/bash
  now=`date "+%Y.%m.%d %H:%M:%S"`
  echo "Phone number?"
  read phone
  echo "Name?"
  read name
  echo "Issue?"
  read issue
  echo "$now/$phone/$name/$issue">>data.txt
  [root@localhost ~]
  # ./note.sh
  Phone number?
  123
  Name?
  Jim
  Issue?
  Script hanging.
  [root@localhost ~]
  # cat data.txt
  2015.04.23 21:38:56/123/Jim/Script hanging.
  [root@localhost ~]
  #
  嗯…… 我们的脚本看起来有点丑啊,让我们来美化一下。如果你要手动读取read命令,你会发现read命令也可以显示一些信息。要实现该功能,我们应该使用-p键加上信息:
  [root@localhost ~]
  # cat note.sh
  #!/bin/bash
  now=`date "+%Y.%m.%d %H:%M:%S"`
  read -p "Phone number: " phone
  read -p "Name: " name
  read -p "Issue: " issue
  echo "$now/$phone/$name/$issue">>data.txt
  你可以直接从控制台查找到各个命令的大量有趣的信息,只需输入:man read, man echo, man date, man ……
  同意吗?它看上去是舒服多了!
  [root@localhost ~]
  # ./note.sh
  Phone number: 321
  Name: Susane
  Issue: Mouse was stolen
  [root@localhost ~]
  # cat data.txt
  2015.04.23 21:38:56/123/Jim/Script hanging.
  2015.04.23 21:43:50/321/Susane/Mouse was stolen
  [root@localhost ~]
  #
  光标在消息的后面(不是在新的一行中),这有点意思。(LCTT 译注:如果用 echo 命令输出显示的话,可以用 -n 参数来避免换行。)
  循环
  是时候来改进我们的脚本了。如果用户一整天都在接电话,如果每次都要去运行,这岂不是很麻烦?让我们让这些活动都永无止境地循环去吧:
  [root@localhost ~]
  # cat note.sh
  #!/bin/bash
  while true
  do
  read -p "Phone number: " phone
  now=`date "+%Y.%m.%d %H:%M:%S"`
  read -p "Name: " name
  read -p "Issue: " issue
  echo "$now/$phone/$name/$issue">>data.txt
  done
  我已经交换了read phone和now=date行的位置。这是因为我想要在输入电话号码后再获得时间。如果我把它放在循环的首行,那么循环一次后,变量 now 会在数据存储到文件中后马上获得时间。而这并不好,因为下一次呼叫可能在20分钟后,甚至更晚。
  [root@localhost ~]
  # ./note.sh
  Phone number: 123
  Name: Jim
  Issue: Script still not works.
  Phone number: 777
  Name: Daniel
  Issue: I broke my monitor
  Phone number: ^C
  [root@localhost ~]
  # cat data.txt
  2015.04.23 21:38:56/123/Jim/Script hanging.
  2015.04.23 21:43:50/321/Susane/Mouse was stolen
  2015.04.23 21:47:55/123/Jim/Script still not works.
  2015.04.23 21:48:16/777/Daniel/I broke my monitor
  [root@localhost ~]
  #
  注意: 要从无限循环中退出,你可以按[Ctrl]+[C]键。Shell会显示^表示 CTRL 键。
  使用管道重定向
  让我们添加更多功能到我们的“弗兰肯斯坦(Frankenstein)”,我想要脚本在每次呼叫后显示某个统计数据。比如说,我想要查看各个号码呼叫了我几次。对于这个,我们应该cat文件data.txt:
  [root@localhost ~]
  # cat data.txt
  2015.04.23 21:38:56/123/Jim/Script hanging.
  2015.04.23 21:43:50/321/Susane/Mouse was stolen
  2015.04.23 21:47:55/123/Jim/Script still not works.
  2015.04.23 21:48:16/777/Daniel/I broke my monitor
  2015.04.23 22:02:14/123/Jimmy/New script also not working!!!
  [root@localhost ~]
  #
  现在,所有输出我们都可以重定向到cut命令,让cut来把每行切成一块一块(我们使用分隔符“/”),然后打印第二个字段:
  [root@localhost ~]
  # cat data.txt | cut -d"/" -f2
  123
  321
  123
  777
  123
  [root@localhost ~]
  #
  现在,我们可以把这个输出重定向打另外一个命令sort:
  [root@localhost ~]
  # cat data.txt | cut -d"/" -f2|sort
  123
  123
  123
  321
  777
  [root@localhost ~]
  #
  然后只留下的行。要统计条目,只需添加-c键到uniq命令:
  [root@localhost ~]
  # cat data.txt | cut -d"/" -f2 | sort | uniq -c
  3 123
  1 321
  1 777
  [root@localhost ~]
  #
  只要把这个添加到我们的循环的后:
  #!/bin/bash
  while true
  do
  read -p "Phone number: " phone
  now=`date "+%Y.%m.%d %H:%M:%S"`
  read -p "Name: " name
  read -p "Issue: " issue
  echo "$now/$phone/$name/$issue">>data.txt
  echo "===== We got calls from ====="
  cat data.txt | cut -d"/" -f2 | sort | uniq -c
  echo "--------------------------------"
  done
  运行:
  [root@localhost ~]
  # ./note.sh
  Phone number: 454
  Name: Malini
  Issue: Windows license expired.
  ===== We got calls from =====
  3 123
  1 321
  1 454
  1 777
  --------------------------------
  Phone number: ^C
  当前场景贯穿了几个熟知的步骤:
  显示消息
  获取用户输入
  存储值到文件
  处理存储的数据
  但是,如果用户有点责任心,他有时候需要输入数据,有时候需要统计,或者可能要在存储的数据中查找一些东西呢?对于这些事情,我们需要使用switches/cases,并知道怎样来很好地格式化输出。这对于在shell中“画”表格的时候很有用。