Shell编程从入门到精通——基本文本处理(一)

在Shell编程中用来做文本处理的命令有很多,第一部分,向大家介绍echo、文本的格式化输出希望对你有帮助。

一、使用echo输出文本行

在Shell中使用echo命令输出文本是非常多见的,下面是echo命令的使用语法:
echo [options] string...
在上面的语法中,options表示命令选项,echo常用的命令选项比较少,如下:

  • -n  不在最后自动换行
  • -e  使用反斜杠的解释
  • -E  抑制反斜杠的解释

1.显示普通字符

下面演示如何使用echo命令输出用户提示信息:

#! /usr/bin/env bash

echo -n "What is your first name?"
read first
echo -n "What is your last name?"
read last 

2.显示转义字符

echo命令可以控制输出格式,下表列出了echo命令支持的转义字符:

字符 说明
\a 报警符,相当于ASCII码的 BEL字符
\b 退格符
\c 禁止继续输出文本
\f 换页符
\n 换行符
\r 回车符
\t 水平制表符
\v 垂直制表符
\\ 反斜线

需要注意的是使echo命令支持转义字符,还必须使用-e参数。
下面我们使用\c来禁止继续输出字符:

#! /usr/bin/env bash

echo -e "What is your first name? \c"
read first
echo -e "What is your last name? \c"
read last 

Output:

$ sh test.sh
What is your first name? random
What is your last name? wz

我们可以看到\c字符让echo命令后面的换行并没有执行。

3.显示变量

用户可以使用echo命令将程序中的变量值打印出来。

#! /usr/bin/env bash

echo -e "What is your first name? \c"
read first
echo "Hello $first"
#为了使Shell能正确解析变量名,尽量用花括号将变量括起来
echo -e "What is your last name? \c"
read last
echo "Hello ${last} ${first}"

注意:变量名与不能作为变量名的字符,例如-、’、及/等连接的时候,可以不使用花括号。

4.换行与不换行

在默认情况下,echo命令会在文本的最后输出一个换行符,我们可以使用-n参数让echo禁止输出换行,当然也可以只用-e字符转义\c,禁止输出换行。

5.显示命令执行结果

要显示命令执行结果,我们需要使用反引号将命令括起来:

echo `command`
#! /usr/bin/env bash

# 输出日期信息
echo `date`

Output:

$ sh test.sh
2020年07月 5日 8:48:25

6.使用echo命令将执行结果重定向

在某些情况下,我们可能需要将echo输出的字符保存到文件中,这时就需要用到重定向。
下面是重定向字符:

  • > 当目标文件不存在时,创建文件,并将标准输出保存到文件,文件存在时,则覆盖原文件内容。
  • >> 当目标文件不存在时,创建文件,并将标准输出保存到文件;文件存在时,则追加内容到文件末尾。
  • 1> 将正确输出重定向到目标文件,这里为覆盖操作。
  • 1>> 将正确输出重定向到目标文件,这里为追加操作。
  • 2> 将错误输出重定向到目标文件,这里为覆盖操作。
  • 2>> 将错误输出重定向到目标文件,这里为追加操作。
  • &> 意思是把标准输出和标准错误输出都重定向到目标文件中。
#! /usr/bin/env bash

# 输出日期信息
echo `date` > date.txt

我们查看date.txt文件:

$ cat date.txt
2020年07月 5日 8:58:30

二、文本的格式化输出

1.使用UNIX制表符

制表符的功能可以实现在不使用表格的情况下,在垂直方向上按列对齐文本,在Shell中水平制表符\t比较常见,下面我们使用制表符输出乘法口诀表:

#! /usr/bin/env bash
result=0
for ((i=1;i<10;i++))
do
    for ((j=1;j<=$i;j++))
    do
        let result=i*j
        echo -n -e "$i*$j=$result\t"
    done
    echo ""
done

Output:

$ sh test.sh
1*1=1
2*1=2   2*2=4
3*1=3   3*2=6   3*3=9
4*1=4   4*2=8   4*3=12  4*4=16
5*1=5   5*2=10  5*3=15  5*4=20  5*5=25
6*1=6   6*2=12  6*3=18  6*4=24  6*5=30  6*6=36
7*1=7   7*2=14  7*3=21  7*4=28  7*5=35  7*6=42  7*7=49
8*1=8   8*2=16  8*3=24  8*4=32  8*5=40  8*6=48  8*7=56  8*8=64
9*1=9   9*2=18  9*3=27  9*4=36  9*5=45  9*6=54  9*7=63  9*8=72  9*9=81

2.使用fold命令格式化行

fold命令是将超过指定宽度的文本行进行折叠处理,使得超过指定宽度的字符转到下一行输出。fold命令的语法如下:
fold [options] [file...]
在上面的语法中,options表示选项,fold命令常用的选项如下:

  • -b 按字节计算宽度。默认情况下fold命令按照列计算宽度。
  • -s在空格处折断行。
  • -w指定宽度,默认值是80列。
    file参数用来指定要输出的文件名,可以是多个文件,多个文件通过空格隔开。
    下面我们创建一个文件message.txt,内容如下:
$ cat message.txt
The WithCancel, WithDeadline, and WithTimeout functions take a Context (the parent) and return a derived Context (the child) and a CancelFunc.
Calling the CancelFunc cancels the child and its children, removes the parent's reference to the child, and stops any associated timers. Failing to
call the CancelFunc leaks the child and its children until the parent is canceled or the timer fires. The go vet tool checks that CancelFuncs are
used on all control-flow paths.

接下来我们使用fold命令指定输出的列为90:

$ fold -w 90 message.txt
The WithCancel, WithDeadline, and WithTimeout functions take a Context (the parent) and re
turn a derived Context (the child) and a CancelFunc.
Calling the CancelFunc cancels the child and its children, removes the parent's reference
to the child, and stops any associated timers. Failing to
call the CancelFunc leaks the child and its children until the parent is canceled or the t
imer fires. The go vet tool checks that CancelFuncs are
used on all control-flow paths.

我们可以看到这里的列认为每个字符为一列,但是有个问题,我们可以看到,有的单词被分成了两个单词,这个问题我们可以通过使用-s选项解决。

$ fold -s -w 90 message.txt
The WithCancel, WithDeadline, and WithTimeout functions take a Context (the parent) and
return a derived Context (the child) and a CancelFunc.
Calling the CancelFunc cancels the child and its children, removes the parent's reference
to the child, and stops any associated timers. Failing to
call the CancelFunc leaks the child and its children until the parent is canceled or the
timer fires. The go vet tool checks that CancelFuncs are
used on all control-flow paths.

我们可以看到所有的行尾单词都是完整的。

3.使用fmt命令格式化段落

与fold命令相比,fmt命令提供了更多的功能,其基本语法如下:
fmt [-width] [option]... [file]...
其中-width选项用来指定文本行的列数,默认是75列,即每行显示75个字符。options表示各种命令选项,常用的选项如下列:

  • -c 保留每个段落的前两行的缩进,该段落剩余的行的左边距与第二行相同。
  • -t 与-c基本相同,但是在使用-t选项时,每个段落的第一行和第二行的缩进必须是不相同的,否则第一行将被看作一个单独的段落。
  • -s 只折断超出指定宽度的行,不合并超出指定宽度的行。
  • -u统一空格的个数,单词之间保留一个空格,句子之间保留两个空格。
  • -w 指定每个行的最大宽度,默认值为75列。
    file参数为要格式化的文件名,多个文件以空格隔开。
    下面举个例子:
    我们将message的内容改成:
$ cat message.txt
    The WithCancel, WithDeadline, and WithTimeout functions take a Context (the parent) and
return a derived Context (the child) and a CancelFunc.Calling the CancelFunc cancels the child
and its children, removes the parent's reference to the child, and stops any associated timers.
    The WithCancel, WithDeadline

我们使用-w指定文本的宽度为80列,-c让每个文本段落前面两行的缩进格式保留下来,-s参数避免行的合并。

$ fmt -c -s -w 70 message.txt
    The WithCancel, WithDeadline, and WithTimeout functions take
    a Context (the parent) and
return a derived Context (the child) and a CancelFunc.Calling the
CancelFunc cancels the child
and its children, removes the parent's reference to the child,
and stops any associated timers.
    The WithCancel, WithDeadline

注意:fmt命令着重于段落格式化,另外fmt的-w选项和fold命令的-w选项功能并不相同,前者会考虑单词的完整性,后者则不会。

4.使用rev命令反转字符顺序

rev命令的功能是用来反转文件中的文本行的字符顺序,基本语法如下:
rev [file...]
其中file表示要处理的文件名列表,多个文件以空格隔开:
我们创建一个文件message.txt,内容如下:

$ cat message.txt
10 9 8 7 6 5 4 3 2 1
!dlroW olleH

反转字符串:

$ rev message.txt
1 2 3 4 5 6 7 8 9 10
Hello World!

5.使用pr命令格式化文本页

pr命令是一个非常有用的工具,其主要功能是将文本文件的内容转换成适合打印的格式。基本语法如下:
pr [options] [file]...
同样options表示命令选项,file表示文件,多个文件以空格隔开。
常用的选项如下:

  • -column 指定输出的栏数,默认值为1
  • -a 修改column的显示效果,水平创建栏,与column配合使用。
  • -d 产生两个空格的输出。
  • -F或者-f 使用换页符代替换行符实现分页。
  • -h 指定页眉,如果没有指定,则使用文件名称作为页眉。
  • -l 指定每页的行数,默认为66行。
  • -o 指定每行的缩进的字符数量。
  • -w 指定页面宽度,默认为72个字符。

注意:使用column指定的宽度不能超过屏幕宽度,另外默认情况下,pr命令的分栏是垂直划分的。

我们创建一个文件message.txt,文件内容如下:

$ cat message.txt
Context
parent
and
return
derived
Context
CancelFunc
Calling
CancelFunc
cancels
the
child
its
children
removes
the
parent's
reference
child
and
stops
any
associated
timers

接下来我们使用pr命令格式化输出:

[root@random_wz ~]# pr -h "list word" -f  -4 -a message.txt


2020-07-05 10:50                    list word                     Page 1


Context           parent            and               return
derived           Context           CancelFunc        Calling
CancelFunc        cancels           the               child
its               children          removes           the
parent's          reference         child             and
stops             any               associated        timers
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章