将所有文本从大写转换为小写,反之亦然?


17

我的问题是如何将所有文本从大写转换为小写,反之亦然?那就是改变所有字母的大小写。它必须以sed某种方式进行替换。


4
tr会比sed
choroba 2014年

Answers:


20

这是直接的方法sed

$ echo qWeRtY | sed -e 'y/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/'
QwErTy

或者使用GNU的更简短的方式sed,可以与您的语言环境中存在小写<->大写转换的任何字符一起使用:

$ echo qWeRtY | sed -E 's/([[:lower:]])|([[:upper:]])/\U\1\L\2/g'
QwErTy

如果可以使用其他工具,例如:

perl (仅限ASCII字母):

$ echo qWeRtY | perl -pe 'y/[a-z][A-Z]/[A-Z][a-z]/'
QwErTy

perl (更普遍):

$ echo 'αΒγ' | perl -Mopen=locale -pe 's/(\p{Ll})|(\p{Lu})/uc($1).lc($2)/ge'
ΑβΓ

3
您的第二个假设sed输入中使用GNU 和备用大小写。使用sed -re 's/([[:lower:]]?)([[:upper:]]?)/\U\1\L\2/g'代替(仍然是GNU特定的)。第一个仅转换26个ASCII拉丁字母,而第二个转换由您的语言环境识别的任何字母。在tr一个只能使在ASCII语言环境中的意义。在perl一个只适用于ASCII拉丁字母。
斯特凡Chazelas

16

POSIXly只能sed通过提供您要翻译的完整字母集来完成,如@cuonglm所示

tr不过可以做到这一点,这tr就是(音译)的含义:

tr '[:lower:][:upper:]' '[:upper:][:lower:]'

但是,在Linux上有局限性。在tr基于Linux的系统上常见的3种实现中:

  • 使用GNU tr时,仅适用于单字节字符集。例如,Stéphane Chazelas在UTF-8语言环境中,用sTéPHANE cHAZELAS代替sTÉPHANE cHAZELAS。这是GNU的已知限制tr
  • tr从传家宝工具箱中,不工作(你stéphane chazelas)。
  • 那不是busybox tr会做的事情。

在FreeBSD上可以正常工作。您希望它在经过认证的Unix系统中也能正常工作。


bash外壳有一个专门的操作:

in=AbCdE
out=${in~~}

zsh -o extendedglob

out=${in//(#b)(([[:lower:]])|([[:upper:]]))/${(U)match[2]}${(L)match[3]}}

那么在台式机世界中,只有OSX吗?为什么不起作用?是否只是不同的实现,因为重音字符的小写版本与其对应的大写字符之间的十六进制值似乎存在恒定偏移量?

1
@illuminÉ,不确定桌面世界的含义。AFAICS,问题出在GNU上,大多数Unices都有“桌面”。除了ASCII和一些iso8859字符集,我不知道您可以概括十六进制偏移量的内容,而对于类似UTF-8的编码则没有意义。例如在UTF-8中,大写字母(e2 b4 a0)是(e1 83 80);两者i(69)和ı(C4 B1)具有I(49)为大写(除了在土耳其语言环境iİ)。它不适用于GNU的原因tr是GNU tr使用字节而不是字符。
斯特凡Chazelas

我的意思是主流,但实际上没有任何意义,因此多谢大家注意。我只是看了法语的重音字符(实际上只是“é”),并做了非常简单的假设,再次忘记了它与字节有关。但是传家宝之一?我将再次阅读该答案!

1
@illuminÉ,对于传家宝,这是一个不同的问题,似乎它仅支持出现一次[:lower:]or [:upper:](因此忽略第一个)。即使是法语,œ -> Œc5 93 -> c5 92使用UTF-8和bd -> bciso8859-15。
斯特凡Chazelas

2

尽管它具有与trStéphaneChazelas提供的解决方案相同的局限性,但这是另一种实现方法:

{   echo QWERTYqwerty | dd conv=lcase
    echo QWERTYqwerty | dd conv=ucase 
} 2>/dev/null

输出值

qwertyqwerty
QWERTYQWERTY

我将其转储stderr/dev/null那里,因为dd还提供了其对2文件描述符的所有操作的统计信息。根据您正在执行的操作,这可能会很有用,但不适用于本演示。您可以执行的所有其他操作dd仍然适用,例如:

echo QWERTYqwerty | dd bs=1 cbs=6 conv=unblock,ucase 2>/dev/null

输出:

QWERTY
QWERTY

不过,它不会交换大小写(因为in aBc不会转换为AbC)。
斯特凡Chazelas

1
@StéphaneChazelas-是的,但是除非我误解了,否则这不是问题,不是吗?
mikeserv

2

如果您的主要目标是将文件从下层类转换为上层类,那么为什么不使用trSTDOUT转换文件:

$cat FILENAME | tr a-z A-Z > FILENAME2

FILENAME您的原始文件在哪里。FILENAME2转换后的输出文件在哪里。


它不适用于重音字符,é例如(至少在我的文件中)。
Sigur

1

使用awk

awk '{print tolower($0)}' file.txt | tee file.txt

您确定这将起作用吗?>file.txt将通过截断文件开始
iruvar

2
那么您显然没有尝试过。
斯特凡Chazelas

0

ruby 有一个字符串方法,类似命令行中的用法 perl

$ echo 'qWeRtY' | ruby -pe '$_.swapcase!'
QwErTy

另请参见ruby-doc编码

$ ruby -e 'puts Encoding.default_external'
UTF-8
$ echo 'αΒγ'  | ruby -pe '$_.swapcase!'
ΑβΓ

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.