字数 2976,阅读大约需 15 分钟
tr命令是Linux系统中处理字符的“轻量小能手”,主打字符翻译、重复字符压缩、指定字符删除三大核心功能,它从标准输入读取字符流,处理后直接输出到标准输出,没有文件读写的能力,纯内存字符流处理,在日常文本快速处理、脚本编写中特别实用。
本文会从基础语法、核心选项、字符集表示方法,到经典实用场景,用浅显的语言+丰富示例讲透tr命令。
tr [OPTION]... STRING1 [STRING2]OPTION:tr的功能选项,必须写在字符集前面,多个选项可组合使用;STRING1/STRING2:字符集,tr会将其解析为字符数组ARRAY1/ARRAY2,绝大多数场景下STRING2可选;tr命令本质上只做四类操作,所有用法都是这四类的组合:
tr的选项不多,共4个核心功能选项,均支持短选项和长选项,下面逐个讲解每个选项的作用,并搭配简单示例帮助理解(示例中用echo提供标准输入,是tr最常用的使用方式)。
作用:不处理STRING1中的字符,反而处理所有不在STRING1中的字符(补集),字符按ASCII码升序排列。
注意:在UTF-8等多字节字符集的系统中使用需谨慎,易出现非预期结果,建议加LC_ALL=C强制单字节解析。
示例:保留输入中的数字,将其他所有字符替换为星号*
# 输入:abc123def456,保留数字,其余替换为*
echo "abc123def456" | tr -c '0-9' '*'
# 输出:***123***456作用:删除输入中属于STRING1的所有字符,此选项下无需指定STRING2(指定了也会被忽略)。
核心:纯删除,无其他额外处理。
示例1:删除输入中的小写字母
echo "Hello123World456" | tr -d 'a-z'
# 输出:H123W456示例2:删除输入中的特殊符号@和#
echo "test@123#linux" | tr -d '@#'
# 输出:test123linux作用:将输入中连续重复的指定字符,压缩为单个字符;若和翻译/删除选项组合,会在翻译/删除后执行压缩。
-s时:压缩STRING1中的连续重复字符;echo "111222333linux444" | tr -s '0-9'
# 输出:123linux4示例2:压缩连续的空格(日常最实用的场景之一)
echo "linux is a free os" | tr -s ' '
# 输出:linux is a free os作用:仅在字符翻译场景下生效(同时指定STRING1和STRING2),将STRING1截断为和STRING2相同的长度,避免字符集长度不一致导致的非预期翻译。
背景:GNU tr默认兼容BSD风格,若STRING1比STRING2长,会将STRING2的最后一个字符重复,补齐到和STRING1同长度;而-t会让tr按System V风格处理,直接截断STRING1。
示例:对比有无-t的翻译结果
# 无-t:STRING1(abc)比STRING2(xy)长,将y重复,a→x,b→y,c→y
echo "abc" | tr 'abc' 'xy'
# 输出:xyy
# 有-t:截断STRING1为ab,a→x,b→y,c不处理(原封不动)
echo "abc" | tr -t 'abc' 'xy'
# 输出:xyctr的STRING1和STRING2不是正则表达式,只是字符数组,但支持多种字符集简写方式,这是tr的核心灵活点,也是新手容易搞混的地方,下面讲透所有合法的字符表示方法。
直接写字符即可,适用于少量字符的场景,例如:
# 将a换成x,b换成y
echo "abcab" | tr 'ab' 'xy'
# 输出:xycxy支持常见的转义字符,用于表示不可见的控制字符,核心转义序列如下:
示例:将制表符\t替换为空格
echo "linux\tis\tfree" | tr '\t' ' '
# 输出:linux is free示例:用八进制\012表示换行(等价于\n)
echo "linux is free" | tr ' ' '\012'
# 输出:linux
# is
# free用M-N表示从字符M到字符N的连续字符,按ASCII码升序排列,适用于连续字符的场景,例如:
0-9:所有数字a-z:所有小写字母A-Z:所有大写字母a-Z:所有大小写字母(部分系统支持)示例:小写字母转大写字母
echo "hello linux" | tr 'a-z' 'A-Z'
# 输出:HELLO LINUX注意:字符范围仅在Clocale下可移植,EBCDIC编码的系统中A-Z并非连续,建议优先用字符类(下文)。
仅在STRING2中生效,用于快速生成重复的字符,避免手动输入多次:
[C*N]:生成N个字符C(N为数字,0开头表示八进制,0值则忽略);[C*]:将C重复,补齐到和STRING1相同的长度。示例1:生成6个y,替换数字0-9为y([y*6]仅前6个数字替换为y,后4个按GNU默认规则也替换为y)
echo "1234567890" | tr '0-9' '[y*6]'
# 输出:yyyyyyyyyy示例2:将所有非字母的字符替换为换行(用[\n*]自动补齐补集长度)
echo "linux123is@free" | tr -c 'a-z' '[\n*]'
# 输出:linux
# is
# free最推荐的方式,可移植性最高,用[:CLASS:]表示一类字符,注意前后的冒号不能少,核心字符类如下(必记):
核心规则:
[:lower:]和[:upper:]可在STRING2中使用,且需和STRING1的对应类位置一致(用于大小写转换)。示例1:用字符类实现小写转大写(最便携)
echo "hello LINUX" | tr '[:lower:]' '[:upper:]'
# 输出:HELLO LINUX示例2:删除所有标点符号
echo "hello! linux, how are you?" | tr -d '[:punct:]'
# 输出:hello linux how are you基本无实用价值,本意是表示和字符C等价的所有字符(适配非英语字母),但GNU tr中每个字符的等价类只有自己,因此几乎不用,了解即可。
tr的强大之处在于选项组合+字符集灵活搭配,下面讲解日常工作中最常用的场景,覆盖翻译、删除、压缩的各种组合,直接抄作业即可。
三种实现方式,推荐第三种字符类方式,可移植性最高:
# 方式1:手动写字母
echo "Hello Linux" | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
# 方式2:字符范围
echo "Hello Linux" | tr 'a-z' 'A-Z'
# 方式3:字符类(推荐)
echo "Hello Linux" | tr '[:lower:]' '[:upper:]'
# 大写转小写,反向即可
echo "Hello Linux" | tr '[:upper:]' '[:lower:]'用-s压缩连续的换行符\n,直接消除空行:
# 原始输入有连续换行,压缩为单个换行
echo -e "linux\n\n\nis\n\nfree" | tr -s '\n'
# 输出:
# linux
# is
# free
# 也可将换行压缩为空格,把多行转为一行
echo -e "linux\nis\nfree" | tr -s '\n' ' '
# 输出:linux is free结合-d和字符类,精准删除指定类型字符:
# 删除所有数字
echo "linux123is456free789" | tr -d '[:digit:]'
# 输出:linuxisfree
# 删除所有字母
echo "linux123is456free789" | tr -d '[:alpha:]'
# 输出:123456789结合-c(补集)和-s(压缩),实现“按字母/数字分割行”,适合提取文本中的关键词:
# 非字母数字替换为换行,再压缩连续换行
echo "linux!123is@free#os" | tr -cs '[:alnum:]' '[\n*]'
# 输出:
# linux
# 123
# is
# free
# osLinux文本文件中常出现^M(\r)等Windows控制字符,用tr快速删除:
# 删除回车符\r(解决Windows文件在Linux中的换行问题)
cat test.txt | tr -d '\r' > new_test.txt
# 删除所有控制字符
cat test.txt | tr -d '[:cntrl:]' > new_test.txt结合tr和uniq,先将文本处理为“一行一个单词”,再统计重复项,这是tr在脚本中的经典用法:
# 脚本实现:提取重复单词,忽略大小写和标点
cat text.txt \
| tr -s '[:punct:][:blank:]' '[\n*]' \ # 标点/空白替换为换行,压缩连续换行
| tr '[:upper:]' '[:lower:]' \ # 全部转为小写
| uniq -d # 仅显示重复的行(重复单词)tr支持多字符一对一翻译,按字符集的顺序依次替换:
# 将a→1,b→2,c→3
echo "abcabc123" | tr 'abc' '123'
# 输出:123123123
# 将空格→_,Tab→-
echo "linux is\tfree" | tr ' \t' '_-'
# 输出:linux_is-freesed/awk;a-z/A-Z仅在Clocale下有效,跨系统建议用[:lower:]/[:upper:];-的处理:若要处理-本身,需将其放在字符集最后,或用--终止选项解析:# 正确删除-:放在最后
echo "linux-123-os" | tr -d '0-9-'
# 正确删除-:用--终止选项
echo "linux-123-os" | tr -d -- '-0-9'# a出现3次,取最后一个,a→z
echo "abc" | tr 'aaa' 'xyz'
# 输出:zbcsed。日常工作中,tr常和echo/cat/uniq/sort等命令配合使用,在文本快速处理、shell脚本中能大幅提升效率,熟记本文的经典示例,即可解决90%的字符处理需求。