Konversi semua teks dari huruf besar ke huruf kecil dan sebaliknya?

17

Pertanyaan saya adalah bagaimana saya bisa mengubah semua teks dari huruf besar menjadi huruf kecil dan sebaliknya? Itu untuk mengubah kasus semua huruf. Itu harus dilakukan dengan sedpenggantian entah bagaimana.

MEZesUBI
sumber
4
trakan lebih cocok daripada sed.
choroba

Jawaban:

20

Inilah cara langsung sed:

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

atau cara yang lebih pendek dengan GNU sed, bekerja dengan karakter apa pun yang ada <-> konversi huruf kecil di lokal Anda:

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

jika Anda dapat menggunakan alat lain, seperti:

perl (terbatas pada surat ASCII):

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

perl (lebih umum):

$ echo 'αΒγ' | perl -Mopen=locale -pe 's/(\p{Ll})|(\p{Lu})/uc($1).lc($2)/ge'
ΑβΓ
cuonglm
sumber
3
Yang kedua mengasumsikan GNU seddan kasing alternatif di input. Gunakan sed -re 's/([[:lower:]]?)([[:upper:]]?)/\U\1\L\2/g'sebagai gantinya (masih spesifik GNU). Yang pertama hanya mengonversi 26 huruf latin ASCII, sedangkan yang kedua mengonversi setiap huruf yang dikenali oleh lokal Anda. Yang trhanya masuk akal di lokal ASCII. Yang perlsatu hanya berfungsi untuk huruf latin ASCII.
Stéphane Chazelas
16

POSIXly, itu tidak bisa dilakukan sedkecuali dengan menyediakan set lengkap surat yang ingin Anda transliterasikan seperti yang ditunjukkan oleh @cuonglm .

Itu bisa dilakukan dengan tr, dan itu truntuk (transliterate):

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

Namun, di Linux, ada batasannya. Dari 3tr implementasi yang biasa ditemukan pada sistem berbasis Linux:

  • dengan GNU tr, yang hanya berfungsi untuk set karakter byte tunggal. Misalnya, di Stéphane Chazelasdalam lokal UTF-8, yang memberi sTéPHANE cHAZELASbukansTÉPHANE cHAZELAS . Itu adalah keterbatasan GNU tr.
  • dengan tr dari toolchest heirloom, itu tidak berhasil (Anda dapatkan stéphane chazelas).
  • Itu bukan jenis busybox tr .

Pada FreeBSD itu berfungsi dengan baik. Anda akan mengharapkannya berfungsi dengan baik di sistem Unix bersertifikat juga.


The bashshell memiliki operator khusus untuk itu:

in=AbCdE
out=${in~~}

Dengan zsh -o extendedglob:

out=${in//(#b)(([[:lower:]])|([[:upper:]]))/${(U)match[2]}${(L)match[3]}}
Stéphane Chazelas
sumber
Jadi di dunia desktop hanya OSX yang melakukannya? Mengapa itu tidak berhasil? Apakah hanya implementasi yang berbeda karena tampaknya ada offset konstan dalam nilai hex antara versi huruf kecil dari aksen char dan rekan huruf besar itu?
1
@ illuminÉ, tidak yakin apa yang Anda maksud dengan dunia desktop . AFAICS, masalahnya adalah dengan GNU, sebagian besar Unices memiliki "desktop". Terlepas dari ASCII dan beberapa rangkaian iso8859, saya tidak menyadari bahwa Anda dapat menggeneralisasi hal hex offset, dan itu tidak masuk akal dengan pengkodean seperti UTF-8. Misalnya dalam UTF-8, huruf besar (e2 b4 a0) adalah (e1 83 80); baik i(69) dan ı(c4 b1) memiliki I(49) sebagai huruf besar (kecuali di lokal Turki di mana imenjadi İ). Alasan tidak bekerja dengan GNU tradalah karena GNU trbekerja dengan byte dan bukan karakter.
Stéphane Chazelas
Saya semacam berarti arus utama tetapi tidak masuk akal benar-benar terima kasih untuk kepala. Saya hanya melihat karakter aksen Prancis (dan benar-benar hanya "é") dan membuat asumsi yang sangat sederhana, lupa lagi bahwa ini tentang byte. Tapi yang pusaka? Saya akan membaca jawaban itu lagi!
1
@ illuminÉ, untuk pusaka, ini masalah yang berbeda, sepertinya hanya mendukung satu kejadian [:lower:]atau [:upper:](jadi yang pertama diabaikan). Bahkan di Perancis, œ -> Œadalah c5 93 -> c5 92dalam UTF-8 dan bd -> bcdi iso8859-15.
Stéphane Chazelas
2

Meskipun ini memiliki keterbatasan yang sama yang telah disebutkan sebagai trsolusi yang ditawarkan oleh Stéphane Chazelas, ini adalah cara lain untuk melakukannya:

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

KELUARAN

qwertyqwerty
QWERTYQWERTY

Saya membuang stderrke /dev/nullsana karena ddjuga menyediakan statistik dari semua operasinya pada 2deskriptor file. Ini bisa bermanfaat tergantung pada apa yang Anda lakukan, tetapi tidak untuk demonstrasi ini. Semua hal lain yang dapat Anda lakukan ddmasih berlaku, misalnya:

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

KELUARAN:

QWERTY
QWERTY
mikeserv
sumber
Itu tidak menukar kasus (karena aBctidak dikonversi ke AbC).
Stéphane Chazelas
1
@ StéphaneChazelas - benar, tapi kecuali saya salah paham, bukan itu pertanyaannya, kan?
mikeserv
2

Jika tujuan utama Anda adalah untuk mengkonversi file dari kelas bawah ke kelas atas, mengapa tidak Anda gunakan trdan STDOUTuntuk mengkonversi file Anda:

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

Di mana FILENAMEfile asli Anda. Di mana FILENAME2file hasil konversi Anda.

Rick
sumber
Itu tidak berfungsi dengan karakter beraksen, seperti émisalnya (setidaknya dalam file saya).
Sigur
1

menggunakan awk:

awk '{print tolower($0)}' file.txt | tee file.txt
Hackaholic
sumber
Anda yakin ini akan berhasil? >file.txtakan memulai dengan memotong file
iruvar
2
Maka Anda jelas belum mencobanya.
Stéphane Chazelas
0

ruby memiliki metode string untuk itu, penggunaan yang serupa dari baris perintah seperti perl

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

Lihat juga Encoding ruby-doc

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

Buat hal yang sederhana tetap sederhana. Filter yang dirancang untuk menerjemahkan karakter adalah tr.

echo 1ude1UDE | tr [:upper:][:lower:] [:lower:][:upper:]
rogelio
sumber
1
Versi yang rusak (karena tanda kutip yang hilang di sekitar operator globbing) dari jawaban yang sudah diberikan 2 tahun sebelumnya
Stéphane Chazelas