แปลงข้อความทั้งหมดจากตัวพิมพ์ใหญ่เป็นตัวพิมพ์เล็กและในทางกลับกัน


17

คำถามของฉันคือฉันจะแปลงข้อความทั้งหมดจากตัวพิมพ์ใหญ่เป็นตัวพิมพ์เล็กและในทางกลับกันได้อย่างไร นั่นคือการเปลี่ยนแปลงกรณีของตัวอักษรทั้งหมด มันจะต้องมีการsedเปลี่ยนอย่างใด


4
trsedจะเหมาะสมกว่า
choroba

คำตอบ:


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
อันที่สองของคุณถือว่า GNU sedและตัวพิมพ์สำรองในอินพุต ใช้sed -re 's/([[:lower:]]?)([[:upper:]]?)/\U\1\L\2/g'แทน (ยังคง GNU เฉพาะ) ตัวแรกจะแปลงตัวอักษรละติน 26 ASCII เพียงตัวเดียวในขณะที่ตัวที่สองจะแปลงตัวอักษรใด ๆ ที่เป็นที่ยอมรับโดยสถานที่ของคุณ สิ่งที่trเหมาะสมใน ASCII locales เท่านั้น perlหนึ่งทำงานเฉพาะสำหรับตัวอักษรละติน ASCII
Stéphane Chazelas

16

POSIXly ที่ไม่สามารถทำได้ด้วยการsedยกเว้นโดยการให้ชุดที่สมบูรณ์ของตัวอักษรที่คุณต้องการในการแปลเป็น@cuonglm ได้แสดงให้เห็น

มันสามารถทำได้ด้วยtrและนั่นคือสิ่งที่trมีไว้สำหรับ (นักแปล):

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

อย่างไรก็ตามบน Linux มันมีข้อ จำกัด จาก 3 trการใช้งานที่พบได้ทั่วไปบนระบบที่ใช้ Linux:

  • ด้วย GNU trที่ใช้งานได้กับชุดอักขระไบต์เดียวเท่านั้น ยกตัวอย่างเช่นในStéphane ChazelasUTF-8 สถานที่ให้แทนsTéPHANE cHAZELAS sTÉPHANE cHAZELASนั่นเป็นข้อ จำกัด ที่เป็นที่รู้จักของ trGNU
  • ด้วยtrจากเครื่องมือมรดกสืบทอดที่ไม่ทำงาน (คุณได้รับstéphane chazelas)
  • นั่นไม่ใช่สิ่งที่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 บางส่วนฉันไม่ทราบว่าคุณสามารถสรุปสิ่งชดเชยแบบ hex และไม่สมเหตุสมผลกับการเข้ารหัสเช่น UTF-8 ยกตัวอย่างเช่นใน UTF-8 ตัวพิมพ์ใหญ่(e2 b4 a0) คือ(e1 83 80) ทั้งi(69) และı(c4 b1) มีI(49) เป็นตัวพิมพ์ใหญ่ (ยกเว้นในที่ตั้งภาษาตุรกีที่iกลายเป็นİ) เหตุผลที่มันใช้ไม่ได้กับ GNU trก็คือ GNU นั้นใช้trงานได้กับไบต์และไม่ใช่ตัวอักษร
Stéphane Chazelas

ฉันหมายถึงกระแสหลัก แต่มันก็ไม่สมเหตุสมผลจริง ๆ ขอบคุณสำหรับหัวขึ้น ฉันเพิ่งดูตัวอักษรที่เน้นเสียงภาษาฝรั่งเศส (และจริงๆแค่ "é") และตั้งสมมติฐานอย่างง่าย ๆ และลืมอีกครั้งว่ามันเกี่ยวกับไบต์ แต่มรดกตกทอดหนึ่ง ฉันจะไปอ่านคำตอบนั้นอีกครั้ง!

1
@ illuminÉสำหรับมรดกตกทอดมันเป็นปัญหาที่แตกต่างกันดูเหมือนว่าจะรองรับการเกิดขึ้นเพียงครั้งเดียว[:lower:]หรือ[:upper:](ดังนั้นรายการแรกจะถูกละเว้น) แม้แต่ในภาษาฝรั่งเศสœ -> Œก็อยู่c5 93 -> c5 92ใน UTF-8 และbd -> bcใน iso8859-15
Stéphane Chazelas

2

แม้ว่านี่จะมีข้อ จำกัด เช่นเดียวกันกับที่กล่าวไว้แล้วว่าเป็นtrวิธีการแก้ปัญหาที่นำเสนอโดยStéphane Chazelas แต่ก็เป็นอีกวิธีที่จะทำได้:

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

เอาท์พุท

qwertyqwerty
QWERTYQWERTY

ฉันถ่ายโอนstderrไปที่/dev/nullนั่นเพราะddยังให้สถิติของการดำเนินงานทั้งหมดใน2file descriptor สิ่งนี้มีประโยชน์ขึ้นอยู่กับสิ่งที่คุณทำ แต่ไม่ใช่สำหรับการสาธิตนี้ สิ่งอื่น ๆ ทั้งหมดที่คุณสามารถทำได้กับddยังใช้เช่น:

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

เอาท์พุท:

QWERTY
QWERTY

มันไม่ได้สลับกรณี (แม้ว่าaBcจะไม่ถูกแปลงเป็นAbC)
Stéphane Chazelas

1
@ StéphaneChazelas - จริง แต่ถ้าฉันเข้าใจผิดนั่นไม่ใช่คำถามใช่มั้ย
mikeserv

2

หากวัตถุประสงค์หลักของคุณคือการแปลงไฟล์จากคลาสที่ต่ำกว่าเป็นตัวพิมพ์ใหญ่ทำไมคุณไม่ใช้trและSTDOUTแปลงไฟล์ของคุณ:

$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
เห็นได้ชัดว่าคุณไม่ได้ลอง
Stéphane Chazelas

0

ruby มีวิธีสตริงสำหรับการใช้งานที่คล้ายกันจากบรรทัดคำสั่งเช่น perl

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

ดูเพิ่มเติมที่การเข้ารหัสทับทิม doc

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.