我对选项的执行顺序感到困惑tr
。
例如,有这样一个命令:
echo 123 | tr -ct '\n' '0'
这是如何执行的?是-c
先执行还是-t
?
我也对这个命令的结果感到困惑。我以为-c
是先执行,结果是123
,然后-t
会执行,结果是023
,最后是023\n
。但这是错误的,正确的答案是123\n
,我不知道为什么,有人可以告诉我吗?
有趣的是,tr -ct
似乎补充了第一组,然后将其截断到第二组的长度。这可能不是您应该依赖的行为,因为-t
它“首先将 SET1 截断为 SET2 的长度”。
无论如何,明显的效果是-c
首先应用,将第一个集合\n
转换为包含每个字符的集合,但\n
按升序排序(因此第一个字符是 NUL 字符\0
)。然后,-t
应用 ,导致集合被截断为\0
。因此,tr
会将 NUL 字符转换为0
字符。
例如,考虑一下:
$ tr --version
tr (GNU coreutils) 8.13
$ echo -e 'X\0X'
XX
$ echo -e 'X\0X' | tr -ct '\n' '0'
X0X
-c 表示使用 string1 中字符的补码,或者“任何不在 string1 中的字符替换 string1 的值”。
-t 表示将第一组值截断为第二组的长度。String2 的长度只有 1 个字符,因此 string1 被截断为该长度。
换句话说: tr -ct '\n' '0' -> tr -t '\000\001\002...01234...ABCDEF...' '0' -> tr '\000' '0 '
试试这个来测试它:
printf '\000afoo\n' | tr -ct '\na' '7'
“任何不是 '\n' 或 'a' 的字符” (-c) 变为 '\000' (-t) 因为为 string2 指定了 '7',它的长度为 1。现在试试这个:
printf '\000afoo\n' | tr -ct '\na' '[7*]'
“任何不是 '\n' 或 'a' 的字符” (-c) 仍然存在,因为 '7' 用于该集中的任何字符。这是 GNU 和历史 BSD tr 的默认行为,因此如果未指定 -t,则 '7' 与 '[7*]' 一样有效。对于 System V 和 POSIX tr,'[7*]' 是一种重复形式,而 '7' 只是将第一组中的第一个字符替换为 '7',这可以说更直观,并且肯定是您的问题所在的一部分from(如果指定了 -t,GNU tr 将行为更改为 System V)。