在 Linux 中对 tr 使用引号
Using quotes with tr in Linux
我在 Bash 脚本中遇到了一个奇怪的错误。该脚本将用户的输入更改为小写。如下:
# echo AcCCept | tr [:upper:] [:lower:]
我通过添加引号(或双引号)来解决。奇怪的是,在 system-a 上失败的完全相同的命令在 system-b 上运行良好。
system-a有Centos7.5.
system-b有Centos7.4.
然而,Bash 和 tr
版本在两者上完全相同。
有问题的系统-a 的输出:
[root@system-a ~]# echo AcCCept | tr [:upper:] [:lower:]
tr: misaligned [:upper:] and/or [:lower:] construct
[root@system-a ~]#
[root@system-a ~]#
[root@system-a ~]# echo AcCCept | tr [:upper:] [:lower:]
tr: misaligned [:upper:] and/or [:lower:] construct
[root@system-a ~]# echo AcCCept | tr "[:upper:]" "[:lower:]"
acccept
[root@system-a ~]# bash -version
GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
<http://gnu.org/licenses/gpl.html>
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
[root@system-a ~]# tr --version
tr (GNU coreutils) 8.22
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Written by Jim Meyering.
[root@system-a ~]# cat /etc/redhat-release
CentOS Linux release 7.5.1804 (Core)
[root@system-a ~]#
系统 b 的输出 - 工作正常:
echo AcCCept | tr [:upper:] [:lower:]
acccept
[root@system-b ~]# echo AcCCept | tr "[:upper:]" "[:lower:]"
acccept
[root@system-b ~]# bash -version
GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
[root@system-b ~]# tr --version
tr (GNU coreutils) 8.22
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Written by Jim Meyering.
[root@system-b ~]# cat /etc/redhat-release
CentOS Linux release 7.4.1708 (Core)
[root@system-b ~]#
同一个命令在system-a上失败而在system-b上运行正常的原因是什么?
未加引号时,[...]
受 pathname expansion 约束。例如,如果您的目录中有一个名为 u
的文件,[:upper:]
将扩展到它:
$ ls # dir is empty
$ echo [:upper:] # [:upper:] doesn't expand to anything and gets printed as is
[:upper:]
$ touch u # filename 'u' created
$ echo [:upper:] # [:upper:] expands to 'u'
u
$ echo '[:upper:]' # [:upper:] is protected by quotes and doesn't get expanded
[:upper:]
为什么这是个问题?引用自 man tr
:
tr [OPTION]... SET1 [SET2]
Only [:lower:]
and [:upper:]
are guaranteed to expand
in ascending order; used in SET2
while translating, they may only be used in pairs to specify
case conversion.
这意味着如果你在SET2
中使用[:lower:]
,[:upper:]
或[:lower:]
必须在SET1
中使用。否则你会得到一个错误:
$ tr '[:upper:]' '[:lower:]' <<< "TeXt" # SET1: [:upper:] SET2: [:lower:] => OK
text
$ tr 'u' '[:lower:]' <<< "TeXt" # SET2: [:lower:] SET1: not [:upper:] => ERROR
tr: misaligned [:upper:] and/or [:lower:] construct
$ tr '[:upper:]' 'l' <<< "TeXt" # SET1: [:upper:] SET2: l => OK
lelt
我在 Bash 脚本中遇到了一个奇怪的错误。该脚本将用户的输入更改为小写。如下:
# echo AcCCept | tr [:upper:] [:lower:]
我通过添加引号(或双引号)来解决。奇怪的是,在 system-a 上失败的完全相同的命令在 system-b 上运行良好。
system-a有Centos7.5.
system-b有Centos7.4.
然而,Bash 和 tr
版本在两者上完全相同。
有问题的系统-a 的输出:
[root@system-a ~]# echo AcCCept | tr [:upper:] [:lower:]
tr: misaligned [:upper:] and/or [:lower:] construct
[root@system-a ~]#
[root@system-a ~]#
[root@system-a ~]# echo AcCCept | tr [:upper:] [:lower:]
tr: misaligned [:upper:] and/or [:lower:] construct
[root@system-a ~]# echo AcCCept | tr "[:upper:]" "[:lower:]"
acccept
[root@system-a ~]# bash -version
GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
<http://gnu.org/licenses/gpl.html>
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
[root@system-a ~]# tr --version
tr (GNU coreutils) 8.22
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Written by Jim Meyering.
[root@system-a ~]# cat /etc/redhat-release
CentOS Linux release 7.5.1804 (Core)
[root@system-a ~]#
系统 b 的输出 - 工作正常:
echo AcCCept | tr [:upper:] [:lower:]
acccept
[root@system-b ~]# echo AcCCept | tr "[:upper:]" "[:lower:]"
acccept
[root@system-b ~]# bash -version
GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
[root@system-b ~]# tr --version
tr (GNU coreutils) 8.22
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Written by Jim Meyering.
[root@system-b ~]# cat /etc/redhat-release
CentOS Linux release 7.4.1708 (Core)
[root@system-b ~]#
同一个命令在system-a上失败而在system-b上运行正常的原因是什么?
未加引号时,[...]
受 pathname expansion 约束。例如,如果您的目录中有一个名为 u
的文件,[:upper:]
将扩展到它:
$ ls # dir is empty
$ echo [:upper:] # [:upper:] doesn't expand to anything and gets printed as is
[:upper:]
$ touch u # filename 'u' created
$ echo [:upper:] # [:upper:] expands to 'u'
u
$ echo '[:upper:]' # [:upper:] is protected by quotes and doesn't get expanded
[:upper:]
为什么这是个问题?引用自 man tr
:
tr [OPTION]... SET1 [SET2]
Only
[:lower:]
and[:upper:]
are guaranteed to expand in ascending order; used inSET2
while translating, they may only be used in pairs to specify case conversion.
这意味着如果你在SET2
中使用[:lower:]
,[:upper:]
或[:lower:]
必须在SET1
中使用。否则你会得到一个错误:
$ tr '[:upper:]' '[:lower:]' <<< "TeXt" # SET1: [:upper:] SET2: [:lower:] => OK
text
$ tr 'u' '[:lower:]' <<< "TeXt" # SET2: [:lower:] SET1: not [:upper:] => ERROR
tr: misaligned [:upper:] and/or [:lower:] construct
$ tr '[:upper:]' 'l' <<< "TeXt" # SET1: [:upper:] SET2: l => OK
lelt