Chuyển đổi tất cả văn bản từ chữ hoa sang chữ thường và ngược lại?


17

Câu hỏi của tôi là làm thế nào tôi có thể chuyển đổi tất cả văn bản từ chữ hoa sang chữ thường và ngược lại? Đó là thay đổi trường hợp của tất cả các chữ cái. Nó phải được thực hiện với một sedsự thay thế bằng cách nào đó.


4
trsẽ phù hợp hơn sed.
choroba

Câu trả lời:


20

Đây là một cách thẳng vào sed:

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

hoặc một cách ngắn hơn với GNU sed, làm việc với bất kỳ ký tự nào có chuyển đổi chữ thường <-> chữ hoa tồn tại trong ngôn ngữ của bạn:

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

nếu bạn có thể sử dụng các công cụ khác, như:

perl (giới hạn ở các chữ cái ASCII):

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

perl (nói chung hơn):

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

3
Cái thứ hai của bạn giả sử một GNU sedvà trường hợp thay thế trong đầu vào. Sử dụng sed -re 's/([[:lower:]]?)([[:upper:]]?)/\U\1\L\2/g'thay thế (vẫn là GNU cụ thể). Chữ cái đầu tiên chỉ chuyển đổi 26 chữ cái la tinh ASCII, trong khi chữ cái thứ hai chuyển đổi bất kỳ chữ cái nào được nhận diện bởi ngôn ngữ của bạn. Điều trduy nhất có ý nghĩa trong các địa phương ASCII. Các perlngười duy nhất làm việc cho ASCII chữ cái la tinh.
Stéphane Chazelas

16

POSIXly, điều đó không thể được thực hiện sedngoại trừ bằng cách cung cấp bộ chữ cái hoàn chỉnh mà bạn muốn phiên âm như @cuonglm đã hiển thị .

Nó có thể được thực hiện với trmặc dù, và đó là những gì trdành cho (phiên âm):

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

Tuy nhiên, trên Linux, nó có những hạn chế. Trong số 3 trtriển khai thường thấy trên các hệ thống dựa trên Linux:

  • với GNU tr, nó chỉ hoạt động cho các bộ ký tự một byte. Ví dụ, trên Stéphane Chazelascác địa phương UTF-8, cung cấp sTéPHANE cHAZELASthay vì sTÉPHANE cHAZELAS. Đó là một hạn chế đã biết của GNU tr.
  • với trcông cụ gia truyền, nó không hoạt động (bạn nhận được stéphane chazelas).
  • Đó không phải là điều mà busybox trsẽ làm.

Trên FreeBSD hoạt động tốt mặc dù. Bạn cũng mong nó hoạt động tốt trong các hệ thống Unix được chứng nhận.


Các bashvỏ có một nhà điều hành dành riêng cho điều đó:

in=AbCdE
out=${in~~}

Với zsh -o extendedglob:

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

Vậy trong thế giới máy tính để bàn chỉ có OSX làm điều đó? Tại sao nó không thể làm việc? Có phải đó chỉ là các cách triển khai khác nhau vì dường như có một giá trị bù không đổi trong giá trị hex giữa phiên bản chữ thường của char có dấu và đối tác viết hoa của nó?

1
@ illuminÉ, không chắc ý của bạn về thế giới máy tính để bàn . AFAICS, vấn đề là với GNU, hầu hết các Unice đều có "máy tính để bàn". Ngoài ASCII và một số bộ ký tự iso8859, tôi không biết rằng bạn có thể khái quát hóa điều bù hex và điều đó sẽ không có ý nghĩa với các bảng mã như UTF-8. Chẳng hạn, trong UTF-8, chữ hoa (e2 b4 a0) là (e1 83 80); cả i(69) và ı(c4 b1) đều có I(49) là chữ hoa (ngoại trừ ở các địa phương Thổ Nhĩ Kỳ nơi itrở thành İ). Lý do nó không hoạt động với GNU trlà GNU trhoạt động với byte chứ không phải ký tự.
Stéphane Chazelas

Tôi có nghĩa là chủ đạo nhưng nó thực sự không có ý nghĩa vì vậy cảm ơn vì đã ngẩng cao đầu. Tôi chỉ nhìn vào các ký tự có dấu của Pháp (và thực sự chỉ là "é") và đưa ra các giả định rất đơn giản, lại quên rằng đó là về byte. Nhưng gia truyền một? Tôi sẽ đọc câu trả lời đó một lần nữa!

1
@ illuminÉ, đối với gia truyền, đó là một vấn đề khác, có vẻ như nó chỉ hỗ trợ một lần xuất hiện [:lower:]hoặc [:upper:](vì vậy lần đầu tiên bị bỏ qua). Ngay cả trong tiếng Pháp, œ -> Œc5 93 -> c5 92trong UTF-8 và bd -> bciso8859-15.
Stéphane Chazelas

2

Mặc dù điều này có những hạn chế tương tự đã được đề cập như trgiải pháp được cung cấp bởi Stéphane Chazelas, nhưng đó là một cách khác để làm điều đó:

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

ĐẦU RA

qwertyqwerty
QWERTYQWERTY

Tôi đổ stderrvào /dev/nullđó vì ddcũng cung cấp số liệu thống kê về tất cả các hoạt động của nó trên bộ 2mô tả tệp. Điều này có thể hữu ích tùy thuộc vào những gì bạn đang làm, nhưng không phải cho cuộc biểu tình này. ddVí dụ, tất cả những thứ khác bạn có thể làm vẫn áp dụng:

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

ĐẦU RA:

QWERTY
QWERTY

Nó không hoán đổi trường hợp mặc dù (như trong aBckhông được chuyển đổi thành AbC).
Stéphane Chazelas

1
@ StéphaneChazelas - đúng, nhưng trừ khi tôi hiểu lầm, đó không phải là câu hỏi, phải không?
mikeerv

2

Nếu mục tiêu chính của bạn là chuyển đổi một tệp từ lớp dưới sang lớp trên, tại sao bạn không sử dụng trSTDOUTchuyển đổi tệp của mình:

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

FILENAMETập tin gốc của bạn ở đâu FILENAME2Tập tin đầu ra được chuyển đổi của bạn ở đâu


Nó không hoạt động với các ký tự có dấu, éví dụ như (ít nhất là trong tệp của tôi).
Sigur

1

sử dụng awk:

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

bạn có chắc là nó sẽ hoạt động không? >file.txtsẽ bắt đầu bằng cách cắt bớt tệp
iruvar

2
Sau đó, rõ ràng bạn đã không thử nó.
Stéphane Chazelas

0

ruby có một phương thức chuỗi cho điều đó, cách sử dụng tương tự từ dòng lệnh như perl

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

Xem thêm Mã hóa ruby-doc

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

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.