Czy przekonwertować cały tekst z wielkich na małe i odwrotnie?


17

Moje pytanie brzmi: jak mogę przekonwertować cały tekst z wielkich na małe i odwrotnie? To jest zmiana wielkości liter wszystkich liter. sedJakoś trzeba to zrobić z wymianą.


4
trbyłoby bardziej odpowiednie niż sed.
— choroba

Odpowiedzi:


20

Oto prosty sposób na sed:

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

lub w skrócie z GNU sed, pracując z dowolnym znakiem, dla którego w twoim języku istnieje konwersja małych liter <->:

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

jeśli możesz użyć innych narzędzi, takich jak:

perl (ograniczone do liter ASCII):

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

perl (bardziej ogólnie):

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

3
Twój drugi zakłada GNU sedi zmienną wielkość liter na wejściu. Użyj sed -re 's/([[:lower:]]?)([[:upper:]]?)/\U\1\L\2/g'zamiast tego (wciąż specyficzne dla GNU). Pierwszy konwertuje tylko 26 liter łacińskich ASCII, a drugi konwertuje każdą literę rozpoznaną jako taką przez twoje ustawienia regionalne. Ten trma sens tylko w ustawieniach regionalnych ASCII. Ten perldziała tylko dla łacińskich liter ASCII.
— Stéphane Chazelas

16

POSIXly, nie da się tego zrobić sedinaczej niż poprzez dostarczenie pełnego zestawu liter, które chcesz transliterować, jak pokazał @cuonglm .

Można to jednak zrobić za pomocą tri właśnie po to tr(transliteracja):

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

Jednak w systemie Linux ma ograniczenia. Z 3 trimplementacji powszechnie spotykanych w systemach Linux:

  • z GNU tr, który działa tylko dla jednobajtowych zestawów znaków. Na przykład, Stéphane Chazelasw ustawieniach regionalnych UTF-8, to daje sTéPHANE cHAZELASzamiast sTÉPHANE cHAZELAS. To znane ograniczenie GNU tr.
  • z trzestawem narzędzi rodowych, to nie działa (dostajesz stéphane chazelas).
  • Tego nie trzrobi busyboks .

Na FreeBSD działa jednak OK. Można się spodziewać, że będzie działał dobrze również w certyfikowanych systemach uniksowych.


bashPowłoka ma przypisanego operatora na to:

in=AbCdE
out=${in~~}

Z zsh -o extendedglob:

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

Czy w świecie komputerów tylko OSX to robi? Dlaczego to nie działa? Czy to tylko różne implementacje, ponieważ wydaje się, że istnieje ciągłe przesunięcie wartości szesnastkowej między wersją akcentowanego znaku z małą literą a jego wielkimi literami?

1
@ illuminÉ, nie jestem pewien, co masz na myśli przez określenie świata komputerów . AFAICS, problem dotyczy GNU, większość Unices ma „komputery stacjonarne”. Poza ASCII i niektórymi zestawami znaków iso8859, nie jestem świadomy, że można uogólnić przesunięcie heksadecymalne, co nie miałoby sensu w przypadku kodowania takiego jak UTF-8. Na przykład w UTF-8, wielkie litery ⴠ(e2 b4 a0) to Ⴠ(e1 83 80); zarówno i(69), jak i ı(c4 b1) mają I(49) jako wielkie litery (z wyjątkiem tureckich lokalizacji, w których się ipojawia İ). Powodem, dla którego nie działa z GNU, trjest to, że GNU trdziała z bajtami, a nie ze znakami.
— Stéphane Chazelas,

W pewnym sensie miałem na myśli główny nurt, ale to naprawdę nie ma sensu, więc dziękuję za uwagi. Właśnie spojrzałem na francuskie znaki akcentowane (a tak naprawdę po prostu „é”) i podjąłem bardzo uproszczone założenia, zapominając ponownie, że chodzi o bajty. Ale ten rodowy? Przeczytam tę odpowiedź jeszcze raz!

1
@ illuminé, w przypadku pamiątki jest to inny problem, wygląda na to, że obsługuje tylko jedno wystąpienie [:lower:]lub [:upper:](więc pierwszy jest ignorowany). Nawet w języku francuskim œ -> Œjest c5 93 -> c5 92w UTF-8 i bd -> bcw iso8859-15.
— Stéphane Chazelas,

2

Chociaż ma to już te same ograniczenia, co trrozwiązanie oferowane przez Stéphane Chazelas, jest to inny sposób:

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

WYNIK

qwertyqwerty
QWERTYQWERTY

I zrzucić stderrsię /dev/nulltam, ponieważ ddzapewnia również statystyki wszystkich swoich działań na 2deskryptorze pliku. Może to być przydatne w zależności od tego, co robisz, ale nie było w tej demonstracji. ddNadal obowiązują wszystkie inne rzeczy, które możesz zrobić , na przykład:

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

WYNIK:

QWERTY
QWERTY

Nie zamienia jednak sprawy (ponieważ in aBcnie jest konwertowany na AbC).
— Stéphane Chazelas,

1
@ StéphaneChazelas - prawda, ale chyba że źle zrozumiałem, to nie było pytanie, prawda?
— mikeserv

2

Jeśli Twoim głównym celem jest konwersja pliku z klasy niższej do wyższej, dlaczego nie używasz tri STDOUTdo konwersji pliku:

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

Gdzie FILENAMEjest twój oryginalny plik. Gdzie FILENAME2jest przekonwertowany plik wyjściowy.


Nie działało z akcentowanymi znakami, jak éna przykład (przynajmniej w moim pliku).
— Sigur,


0

ruby ma do tego metodę łańcuchową, podobne użycie z linii poleceń jak perl

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

Zobacz także kodowanie ruby-doc

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

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.