แปลงเนื้อหาไฟล์เป็นตัวพิมพ์เล็ก


85

ฉันมีtempไฟล์ที่มีเนื้อหาตัวพิมพ์เล็กและตัวพิมพ์เล็ก

อินพุต

เนื้อหาของtempไฟล์ของฉัน:

hi
Jigar
GANDHI
jiga

ฉันต้องการที่จะแปลงบนไปล่าง

คำสั่ง

ฉันลองคำสั่งต่อไปนี้:

sed -e "s/[A-Z]/[a-z]/g" temp

แต่มีเอาต์พุตผิด

เอาท์พุต

ฉันต้องการมันเป็น:

hi
jigar
gandhi
jiga

สิ่งที่จะต้องมีในแทนส่วนของการโต้แย้งสำหรับsed?


คำตอบ:


122

หากอินพุตของคุณมีอักขระ ASCII เท่านั้นคุณสามารถใช้trlike:

tr A-Z a-z < input 

หรือ (จำได้ง่ายน้อยกว่าและพิมพ์ IMO แต่ไม่ จำกัด เฉพาะตัวอักษรละติน ASCII แม้ว่าในการใช้งานบางอย่างรวมถึง GNU trยัง จำกัด อยู่ที่อักขระไบต์เดียวดังนั้นในตำแหน่งที่ตั้ง UTF-8 ยัง จำกัด อยู่ที่ตัวอักษร ASCII):

tr '[:upper:]' '[:lower:]' < input

ถ้าคุณต้องใช้sed:

sed 's/.*/\L&/g' < input

(ที่นี่สมมติว่ามีการนำ GNU ไปใช้)

ด้วย POSIX sedคุณจะต้องระบุตัวแปลทั้งหมดจากนั้นคุณสามารถเลือกตัวอักษรที่คุณต้องการแปลง:

sed 'y/AǼBCΓDEFGH.../aǽbcγdefgh.../' < input

ด้วยawk:

awk '{print tolower($0)}' < input

3
โปรดทราบว่า\Lเป็นส่วนขยาย GNU
Anthon

\Lใช้งานได้ดีสำหรับฉันจนถึงตอนนี้ ทำให้จุดที่คุณพยายามจะขยาย GNU
JigarGandhi

2
@JigarGandhi sedเป็นคำสั่ง Unix ระบบที่แตกต่างกันมีตัวแปรที่แตกต่างกันซึ่งมีพฤติกรรมและการใช้งาน โชคดีที่ทุกวันนี้มีมาตรฐานที่เป็นไปตามมาตรฐานมากที่สุดเพื่อให้คุณสามารถไว้วางใจคุณลักษณะขั้นต่ำที่ใช้ร่วมกันได้สำหรับทุกคน \Lไม่ได้อยู่ในหมู่พวกเขาและได้รับการแนะนำโดย GNU sed(ตรงกับตัวดำเนินการเดียวกันในมาตรฐานex/ vi) และโดยทั่วไปจะไม่สามารถใช้ได้ในการใช้งานอื่น ๆ
Stéphane Chazelas

9
โปรดทราบว่าtrการใช้งานบางอย่างเช่น GNU trทำงานไม่ถูกต้องในหลาย ๆ โลแคล (ส่วนใหญ่จะเป็นในปัจจุบันลองecho STÉPHANE | tr '[:upper:]' '[:lower:]'ใช้ตัวอย่าง) ในระบบ GNU คุณอาจต้องการsedที่แตกต่างหรือ'sawk tolower()
Stéphane Chazelas

5
sed 's/.*/\L&/g' < inputการแก้ไขเล็กน้อย: การ\1อ้างอิงไปยังสตริงย่อยที่ตรงกันจะใช้งานไม่ได้เว้นแต่คุณจะระบุซับสตริงด้วยวงเล็บตามที่ wurtle ใช้ในการ อย่างไรก็ตามมันค่อนข้างสะอาดกว่าที่จะใช้&เพื่อแสดงการแข่งขันทั้งหมดดังที่แสดง
Edward Brown

30

ใช้เป็นกลุ่มมันง่ายมาก:

$ vim filename
gg0guGZZ

เปิดไฟล์ggไปที่บรรทัด0แรกคอลัมน์แรก ด้วยguG, ลดขนาดตัวอักษรทั้งหมดจนด้านล่างของไฟล์ ZZบันทึกและออก

มันควรจัดการกับอะไรก็ได้ที่คุณโยนไป มันจะไม่สนใจตัวเลขมันจะจัดการกับ ASCII ที่ไม่ใช่

หากคุณต้องการทำสิ่งที่ตรงกันข้ามให้เปลี่ยนตัวอักษรด้านล่างเป็นตัวพิมพ์ใหญ่สลับuเป็น a U: gg0gUGZZและคุณตั้ง


14
ฮ่า ๆ "ง่ายสุด ๆ "
blambert

สิ่งนี้เห็นได้ชัดว่าไม่ค่อยดีสำหรับไฟล์จำนวนมาก
Corey Goldberg

คำตอบที่ฉันชอบที่สุดตอนนี้ !!!!
Mona Jalal

1
@CoreyGoldberg vim file1 file2 fileetcแล้วสิ่งที่ต้องการ:bufdo gg0guG:w<CR>จะอาจจะทำงานสำหรับจำนวนของไฟล์ใด ๆ ยังไม่ได้ทดสอบว่า!
TankorSmash

@TankorSmash ที่ยังไม่ได้ระดับกับขนาดใหญ่จำนวนไฟล์
คอเรย์โกลด์เบิร์ก

17

ฉันชอบddสิ่งนี้ด้วยตัวเอง

<<\IN LC_ALL=C 2<>/dev/null \
dd conv=lcase
hi
Jigar 
GANDHI
jiga
IN

... ได้รับ ...

hi
jigar
ghandi
jiga

LC_ALL=Cคือการปกป้อง multibytes ใด ๆ ในการป้อนข้อมูล - แม้ว่าเมืองหลวงสัญลักษณ์ใด ๆ ที่จะไม่ได้รับการแปลง เช่นเดียวกับ(GNU) tr - แอปทั้งสองมีแนวโน้มที่จะป้อนข้อมูลที่ไม่เหมาะสมในภาษาที่ไม่ใช่ภาษา C iconvสามารถใช้ร่วมกับโซลูชันที่ครอบคลุมได้

การ2>/dev/nullเปลี่ยนเส้นทางทิ้งddรายงานสถานะเริ่มต้นของ - และ stderr หากไม่มีมันก็ddจะติดตามงานที่เสร็จสมบูรณ์เช่นข้อมูลการพิมพ์ข้างต้นเช่นจำนวนไบต์ที่ถูกประมวลผลและอื่น ๆ


วิธีนี้เร็วกว่าการtrจัดการไฟล์ขนาดใหญ่ขอบคุณ!
WhiteWinterWolf

13

คุณยังสามารถใช้ Perl 5:

perl -pe '$_=lc' temp

ตัวเลือกในการ-pบอก Perl $_เพื่อเรียกใช้การแสดงออกที่ระบุครั้งเดียวสำหรับแต่ละบรรทัดของการป้อนข้อมูลพิมพ์ผลที่ได้คือค่าสุดท้ายของ -eระบุว่าโปรแกรมจะเป็นอาร์กิวเมนต์ถัดไปซึ่งตรงข้ามกับไฟล์ที่มีสคริปต์ lcแปลงเป็นตัวพิมพ์เล็ก มันจะทำงานต่อ$_ไป และ$_=บันทึกนั้นอีกครั้งดังนั้นมันจะถูกพิมพ์

รูปแบบที่จะเป็น

perl -ne 'print lc' temp

การใช้-nเป็นเหมือน-pยกเว้นว่า$_จะไม่ได้รับการพิมพ์ในท้ายที่สุด ดังนั้นแทนที่จะบันทึกลงในตัวแปรนั้นฉันจึงรวมคำสั่งการพิมพ์ที่ชัดเจน

ข้อดีอย่างหนึ่งของ Perl ในทางตรงกันข้ามกับ sed คือคุณไม่ต้องการส่วนขยาย GNU ใด ๆ มีโครงการที่จะต้องเข้ากันได้กับสภาพแวดล้อมที่ไม่ใช่ GNU แต่ยังมีการพึ่งพา Perl asa อยู่แล้ว เมื่อเทียบกับtrอาจเป็นไปได้ว่า Perl lcสามารถทำให้สถานที่รับรู้ได้ง่ายขึ้น ดูperllocaleหน้าคนสำหรับรายละเอียด


9

คุณต้องจับรูปแบบที่ตรงกันแล้วใช้มันในการแทนที่ด้วยตัวปรับเปลี่ยน:

sed 's/\([A-Z]\)/\L\1/g' temp

\(...\)"จับ" ข้อความล้อมจับคู่ที่จับครั้งแรกไป\1ที่ติดกับ\2ฯลฯ เลขเป็นไปตามการเปิดวงเล็บในกรณีของการจับภาพที่ซ้อนกัน

การ\Lแปลงรูปแบบการจับเป็นตัวพิมพ์เล็กและยังมี\Uสำหรับตัวพิมพ์ใหญ่


3
คุณไม่จำเป็นต้องทำเช่นนี้ - รูปแบบทั้งหมดมักจะติดอยู่&
mikeserv

จริง แต่แล้วฉันก็พลาดโอกาสที่จะอธิบายการจับภาพการจับคู่ :-)
wurtel

1

นอกเหนือจากคำตอบของ MvG คุณสามารถใช้ Perl 6:

perl6 -pe .=lc temp

นี่คือ $ _ โดยปริยายและคุณไม่จำเป็นต้องใส่เครื่องหมายอัญประกาศเพื่อป้องกันการขยายตัวโดยเชลล์ ($ _ เป็นพารามิเตอร์ Bash พิเศษดูที่: https://www.gnu.org/software/bash/manual/ html_node / Special-Parameters.html )

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