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.