Перетворити весь текст із великого регістру в малі та навпаки?


17

Моє запитання - як я можу перетворити весь текст із великого регістру в малі та навпаки? Тобто змінити регістри всіх букв. Це потрібно sedякось робити із заміною.


4
trбуло б більш придатним, ніж sed.
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 місцях. Той perlпрацює лише для латинських літер ASCII.
Стефан Шазелас

16

POSIX, це неможливо зробити, за sedвинятком надання повного набору букв, які ви хочете транслітерувати, як показало @cuonglm .

Це можна зробити за допомогою, trхоча trсаме для цього (транслітерація):

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

Однак в Linux це обмеження. З трьох trреалізацій, які зазвичай зустрічаються в системах на базі Linux:

  • з GNU tr, що працює лише для однобайтових наборів символів. Наприклад, Stéphane Chazelasу локалі UTF-8, що дає sTéPHANE cHAZELASзамість sTÉPHANE cHAZELAS. Це відоме обмеження GNU tr.
  • з інструментального 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
@ iluminÉ, не впевнений, що ви розумієте під світом робочого столу . 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працює з байтами, а не символами.
Стефан Шазелас

Я начебто мав на увазі мейнстрім, але це не має сенсу, тому дякую за голову. Я просто переглянув французькі символи з наголосом (і справді просто "é") і зробив дуже спрощені припущення, знову забувши, що мова йде про байти. Але реліквія? Я знову поїду прочитати цю відповідь!

1
@ iluminÉ, для реліквія це вже інше питання, схоже, він підтримує лише одне виникнення [:lower:]або [:upper:](тому перший ігнорується). Навіть французькою мовою œ -> Œє c5 93 -> c5 92в UTF-8 та bd -> bcу iso8859-15.
Стефан Шазелас

2

Хоча це має ті самі обмеження, які вже згадувалося, як trрішення, запропоноване Стефаном Шазеласом, це ще один спосіб зробити це:

{   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

Він не змінює справи, хоча (як і в aBcне перетворений AbC).
Стефан Шазелас

1
@ StéphaneChazelas - правда, але якщо я неправильно зрозумів, це не було питанням, чи не так?
mikeserv

2

Якщо ваша основна мета полягає в перетворенні файлу з нижчого класу в верхній клас, чому ви не використовуєте trі STDOUTконвертувати ваш файл:

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

Де FILENAMEваш оригінальний файл. Де FILENAME2ваш перетворений вихідний файл.


Це не працювало з наголошеними символами, як, éнаприклад, (принаймні, у моєму файлі).
Sigur


0

ruby для цього є рядковий метод, аналогічне використання з командного рядка типу perl

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

Див. Також Кодування кодексів ruby-doc

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.