4.19. 你的替换在此

未匹配的标注

4.19 你的替换在此

当使用 grep 时,只要你匹配到这一行就行,很少去关注是如何匹配的。然而当你想要进行一个替换时,你必须考虑匹配的范围。因此,在行上你确实匹配到什么字符?

在本节中,我们将学习几个例子来展示匹配的范围。然后我们将使用一个工作起来类似于 grep 但是也能让你指定一个替换字符串的程序。最后我们将看几个用来描述替换字符串的元字符。

匹配的范围

让我们看下面的正则表达式:

A*Z

这个匹配了 “0 到多个 A 接着 Z”。 它将产生和简单的指定 “Z” 一样的结果。字母 “A” 可以在那里,也可以不在。事实上,字母 “Z” 是唯一匹配到的字符。这里有一个两行的名为 test 的样本文件 :

All of us, including Zippy, our dog
Some of us, including Zippy, our dog

如果我们尝试匹配之前的正则表达式,两行都将被打印出来。

➜ ch03 git:(daily) ✗ grep "A*Z" test
All of us, including Zippy, our dog
Some of us, including Zippy, our dog

有趣的是,这两行真正的匹配都落在 “Z“ 上,而且只在 ”Z“ 上。

我们可以使用 gres 命令来展示匹配的范围。

➜ ch03 git:(daily) ✗ gres "A*Z" "00" test
All of us, including 00ippy, our dog
Some of us, including 00ippy, our dog

我们期望第一行的匹配范围是从 ”A“ 到 ”Z“ 但实际上只有 ”Z“ 是匹配的。如果我们稍微修改一下正则表达式,这个结果可能会更明显。

A.*Z

“.*” 能被解释为任意字符的零或多次出现,这就意味着“任意数量的字符”能被找到,包括完全没有。这整个表达式就能够被评估为“一个 A 跟着任意数量的字符再跟一个 Z”。一个 “A” 是这个模式里面的初始字符,然后 “Z” 是最后一个字符,在中间有任何东西或什么都没有。对同样的两行文件运行 grep 产生一行的输出。我们在匹配内容的下方加上一行插入符号(^)。

➜ ch03 git:(daily) ✗ grep "A.*Z" test
All of us, including Zippy, our dog
^^^^^^^^^^^^^^^^^^^^^^

这个匹配的范围是从 “A” 到 “Z”。同样的正则表达式,还匹配下面这一行字符串:

➜ ch03 git:(daily) ✗ echo "I heard it on radio station WVAZ 1060." | grep "A.*Z"
I heard it on radio station WVAZ 1060.
                              ^^

字符串 “A.*Z” 匹配 “A 接着任意数量(包括0)的字符串,紧接着 Z” 。现在让我们看示例文件 sample,它包含了一系列包含多个 “A” 和 “Z” 出现的类似的示例行。

All of us, including Zippy, our dog
All of us, including Zippy and Ziggy
All of us, including Zippy and Ziggy and Zelda

正则表达式 “A.*Z” 在每个情况下都将匹配最长可能的范围。

➜ ch03 git:(daily) ✗ grep "A.*Z" sample
All of us, including Zippy, our dog
^^^^^^^^^^^^^^^^^^^^^^
All of us, including Zippy and Ziggy
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
All of us, including Zippy and Ziggy and Zelda
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

如果你想匹配最短可能的范围,这会有问题。

gres 程序详解

gres 是进行单次替换的一个程序。

MKS 工具箱——来自 Mortice Kern Systems 公司提供的一套 用于DOS 的 UNIX 实用程序,包含了一个名为 gresglobal regular expression substitution)的有用程序。就像 grep 一样,它在文件中搜索一个模式。然而它允许你对匹配的字符串的指定一个替换字符串。这个程序实际上是一个简化版本的 sed 而且就像 sed 一样,它打印了所有行,不管是不是有替换产生,它不会在这个文件里面进行这个替换。如果你想保存这个改变的话,你必须将程序的输出导入另一个文件。

gres 不是标准 UNIX 的一部分,但是它会是一个很好的工具。它能通过使用一个调用 sed 来完成工作的简单 shell 脚本而被创建。


if [ $# -lt "3" ] 
then 
    echo Usage: gres pattern replacement file
    exit 1
fi
pattern=$1
replacement=$2
if [ -f $3 ] 
then 
    file=$3
else
    echo $3 is not a file.
    exit 1
fi
A="`echo | tr '\012' '\001'`"
sed -e "s$A$pattern$A$replacement$A" $file

在本章的余下部分,我们将使用 gres 来展示替换元字符的使用。记住适用于 gres 的也适用于 sed。这里我们将正则表达式 “A.*Z” 匹配到的字符串替换为两个0(00)。

➜ ch03 git:(daily) ✗ gres "A.*Z" "00" sample
00ippy, our dog
00iggy
00elda

A="echo | tr '\012' '\001'" 这一行是一个生成一个 Control-A 字符来作为 sed替换命令的分隔符的复杂但可移植的方法。这样做极大的降低了在模式或替换文本中出现分隔符的风险。

\012 表示换行符,\001 表示 ^Aecho 命令本身就产生一个换行符,echo | tr '\012' '\001' 就是将 echo 产生的换行符转换为 ^A

本文章首发在 LearnKu.com 网站上。

上一篇 下一篇
讨论数量: 0
发起讨论 只看当前版本


暂无话题~