替换、压缩、删除字符
命令语法格式
tr [OPTION]… SET1 [SET2]
命令描述
命令tr将来自标准输入的数据写入到标准输出,执行以下操作之一:
- 替换,以及可选地缩减结果中的重复字符,
- 缩减重复字符,
- 删除字符,
- 删除字符,然后从结果中缩减重复的字符。
参数SET1和SET2(如果给出)参数定义了一个有序的字符集。下面分别称为SET1和SET2,统称时我们使用setX。这些setX是tr进行操作的输入字符。–complement(-c,-C)选项将SET1替换为其“补充”(“补充”是指所有不在SET1中的字符)。
目前tr完全支持单字节字符。最终它将支持多字节字符;当它支持的时候,-C选项会使它补充字符集,而-c会使它补充一组值。只有当某些值不是字符时,这种区别才有意义,并且只有在输入包含编码错误时,使用多字节编码的区域设置中才有可能。
命令支持的选项及含义
-c, -C, –complement
使用SET1的补集,即处理SET1中以外的字符。
-d, –delete
删除SET1中的字符,而不是默认的翻译。
-s, –squeeze-repeats
删除输入中出现在最后一个SET中的重复字符,并将其替换为单个字符。简单说,把重复字符压缩为一个字符。
-t, –truncate-SET1
先将SET1截断,使其长度等于SET2。
–help
显示帮助信息并退出。
–version
显示版本信息并退出。
字符集:指定字符集
参数SET1和SET2的格式类似于正则表达式的格式;但是,它们不是正则表达式,只是字符列表。在这些字符串中,大多数字符只是表示自己,没有特殊含义。但字符串可以包含下面列出的缩写,这些组合序列是有特殊含义的。其中一些只能在SET1或SET2中使用,如下所述:
反斜线转义
可以识别以下反斜杠转义序列:
上面是支持的所有的转义序列。
范围
符号’m-n’按升序解释为从m到n的所有字符。例如,’0-9’与’0123456789’相同。m应该在n之前;如果不是,则会产生错误。
在GNU的tr中,不支持使用方括号括起的范围语法(System V的语法)。以这种格式指定的翻译操作有时会按预期工作,因为括号通常是代表自身。但是,应该避免使用它们,因为它们有时会出现意外情况。例如,tr -d ‘[0-9]’会删除括号和数字。
许多历史上常见且甚至被接受的范围用途都不具有可移植性。例如,在使用’A-Z’范围时,在EBCDIC主机上’A’到’Z’不是连续的,但它们在ASCII中是连续的。如果你可以依赖于兼容POSIX的tr版本,那么解决这个问题的最好方法就是使用字符类(见下文)。否则,枚举范围内的所有成员是最便携的(也是最难看的)。
重复的字符
参数SET2中使用符号‘[c*n]’表示n个字符’c‘。因此,’[y*6]‘与’yyyyyy‘相同。SET2中的使用符号‘[c*]’表示与SET1中字符个数相同的’c‘。如果’n‘以’0’开头,则以八进制解释,否则以十进制解释。
字符类
符号'[:class:]’会被解释为在类class中预定义的所有字符。除了upper和lower之外,字符不按特定顺序进行解释,它们按升序进行解释。当给出–delete(-d)和–squeeze-repeats(-s)选项时,可以在SET2中使用任何字符类。否则,在SET2中只使用lower和upper字符类,并且仅在SET1中的相同相对位置上指定了相应的字符类(分别为大写和小写)时才接受。这样做指定了大小写转换。给出无效的类名时,会出现错误。可用的class名称如下:
上面是所有的字符类。
等价的类
语法'[=c=]’解释与c等效的所有字符,没有特定的顺序。等价类是一种相对较新的发明,旨在支持非英语字母表。但似乎没有标准的方法来定义它们或确定它们的内容。因此,在GNU tr中它们没有被完全实现;每个字符的等价类仅由该字符组成,没有特别的用途。
翻译:将一组字符更改为另一组字符
当给出SET1和SET2并且未给出–delete(-d)选项时,tr执行转换。命令tr将其标准输入中出现在SET1的每个字符转换为SET2中的相应位置的字符。标准输入中不在SET1中的字符将保持不变。当一个字符在SET1中出现多次,并且对应SET2中不相同的字符时,只使用最后一个字符。例如,这两个命令是等效的:
# tr a z
命令tr的常见用法是将小写字符转换为大写。这可以通过多种方式完成。以下是其中三种:
# tr a-z A-Z
# tr ‘[:lower:]’ ‘[:upper:]’
但请注意,使用上述类似a-z等形式的范围是不可移植的。
当tr执行转换时,参数SET1和SET2通常具有相同的长度。如果SET1比SET2短,则忽略SET2末尾的额外字符,使其与SET1长度相同。
另一方面,使SET1长于SET2是不可移植的;POSIX说结果是未定义的。在这种情况下,BSD的tr根据需要通过重复SET2的最后一个字符,以此来将SET2设置为与SET1相同的长度。System V的tr将SET1截断为SET2的长度。
默认情况下,GNU的tr会处理这种情况,类似于BSD的tr。当给出–truncate-SET1(-t)选项时,GNU的tr会像System V的tr一样处理这种情况。对于除转换之外的操作,将忽略此选项。
在这种情况下,像System V的tr这样的行为会打破相对常见的BSD语言习惯:
因为它只将零字节(NUL,参数SET1的补码中的第一个元素)而不是所有非字母数字转换为换行符。
顺便说一句,上面的习惯用法是不可移植的,因为它使用了范围,并假设换行的八进制代码是012,且假设符合POSIX标准的tr命令。这里有一个更好的方式:
压缩和删除:删除字符
(1)仅给出–delete(-d)选项时,命令tr将删除输入中出现在SET1中的所有字符。
(2)当仅给出–squeeze-repeats(-s)选项,而不进行翻译时,命令tr将输入中那些在SET1中出现的重复序列进行替换,并且该字符只出现一次。
(3)当同时给出–delete和–squeeze-repeats时,命令tr首先使用SET1执行任何删除,然后使用SET2从任何剩余的字符中处理重复。
(4)在翻译时,也可以使用–squeeze-repeats选项,在这种情况下,命令tr首先执行翻译,然后使用SET2从任何剩余的字符中处理重复。
以下是一些示例,用于说明各种选项组合:
#!/bin/sh cat -- "$@" \ | tr -s '[:punct:][:blank:]' '[\n*]' \ | tr '[:upper:]' '[:lower:]' \ | uniq -d
上面这个脚本只是找出重复的单词,不是对其进行去重。
删除一小组字符通常很简单。例如,要删除所有’a’,’x’,’M’,你会这样做:
请注意,在上面的示例中,我们使用了单引号来保护方括号([])不被Shell的解释。
退出状态
退出状态为零表示成功,非零值表示失败。
相关手册
查看在线手册:http://www.gnu.org/software/coreutils/tr
查看info手册:info ‘(coreutils) tr invocation’
参考文献
- man 1 tr, version GNU coreutils 8.28
更新日志
- 10/27/2017 创建文章
- 06/28/2018 修改文章内容