Pomimo tego, że jest bardziej złożona niż najlepiej oceniona odpowiedź, ta w rzeczywistości robi dokładnie to: „pierwszy wielki znak w zmiennej”. Najlepsza odpowiedź nie daje takich wyników. Wygląda na to, że proste odpowiedzi są głosowane chętniej niż te prawidłowe?
Krzysztof Jabłoński
15
@ KrzysztofJabłoński: Właściwie "najlepiej punktowana odpowiedź" poniżej da takie same wyniki jak ta odpowiedź w Bash 4. Ta odpowiedź ma narzut wywołania podpowłoki (kolejnej powłoki), narzut wywołania narzędzia "tr" (inny proces , a nie Bash), narzut związany z użyciem tutaj-doc / string (tymczasowe tworzenie pliku) i używa dwóch podstawień w porównaniu z jedną z najlepiej ocenioną odpowiedzią. Jeśli absolutnie musisz napisać starszy kod, rozważ użycie funkcji zamiast podpowłoki.
Steve
2
Ta odpowiedź zakłada, że dane wejściowe są zapisane małymi literami. Ten wariant nie ma żadnych założeń: $ (tr '[: lower:]' '[: upper:]' <<< $ {foo: 0: 1}) $ (tr '[: upper:]' '[: lower: ] '<<< $ {foo: 1})
Itai Hanski
5
@ItaiHanski OP nie określił, co powinno stać się z pozostałymi postaciami, tylko z pierwszą. Niby chcieli zmienić notQuiteCamelsię NotQuiteCamel. Twój wariant ma efekt uboczny lub zmusza pozostałe do małych liter - kosztem podwojenia liczby podpowłok i procesów tr.
Jesse Chisholm
3
@DanieleOrlando, to prawda, ale to pytanie nie ma innych tagów niż bash.
@CMCDragonkai: Aby zamienić pierwszą literę na małą, użyj "${foo,}". Aby wszystkie litery były małe, użyj "${foo,,}". Aby wszystkie litery były wielkie, użyj "${foo^^}".
Steve
1
Przypadkowo to zauważyłem ${foo~}i ${foo~~}mam taki sam efekt jak ${foo^}i ${foo^^}. Ale nigdy nie widziałem tej alternatywy nigdzie wspomnianej.
mivk
5
to nie działa na komputerach Mac. otrzymuję następujący błąd:bad substitution
Toland Hon
1
@TolandHon: Jak zapewne już się przekonałeś, musisz zaktualizować do wersji 4.x lub wypróbować inne rozwiązanie, jeśli z jakiegoś powodu nie można zaktualizować tego komputera.
nie działa na MacOS10 Lion sed, westchnij, \ u rozszerza się do u zamiast być operatorem.
vwvan
2
@vwvan brew install coreutils gnu-sedi postępuj zgodnie z instrukcjami, aby użyć poleceń bez prefiksu g. Na ile to warte, nigdy nie chciałem uruchamiać wersji tych poleceń dla OSX od czasu otrzymania wersji GNU.
Dziekan
@vwvan: Tak, przepraszam, sedw tym przypadku będziesz potrzebować GNU
Steve
2
@Dean: FWIW, nigdy nie chciałem uruchamiać OSX :-)
Steve
5
Po prostu zmień to na sed 's/./\U&/i będzie działać na POSIX sed.
wreszcie coś, co działa ze zmienną i na Macu! Dziękuję Ci!
OZZIE
4
@DanieleOrlando, nie tak przenośne, jak można by się spodziewać. tr [:lower:] [:upper:]jest lepszym wyborem, jeśli musi działać w języku / ustawieniach regionalnych zawierających litery spoza zakresu a-zlub A-Z.
Można to zrobić również w czystym bashu z bash-3.2:
# First, get the first character.
fl=${foo:0:1}# Safety check: it must be a letter :).if[[ ${fl}==[a-z]]];then# Now, obtain its octal value using printf (builtin).
ord=$(printf '%o'"'${fl}")# Fun fact: [a-z] maps onto 0141..0172. [A-Z] is 0101..0132.# We can use decimal '- 40' to get the expected result!
ord=$(( ord -40))# Finally, map the new value back to a character.
fl=$(printf '%b''\'${ord})
fi
echo "${fl}${foo:1}"
jak zdefiniować foo? Próbowałem, foo = $1ale dostaję tylko-bash: foo: command not found
OZZIE
1
@OZZIE, brak spacji wokół =w zadaniach. To jest coś, co shellcheck.net znajdzie dla Ciebie programowo.
Charles Duffy
Zawsze zapominam o skryptach powłoki .. tylko język, w którym liczy się jedna spacja (przed / po) ... westchnij (python to co najmniej 4, jeśli dobrze pamiętam)
OZZIE
@OZZIE, to musi mieć znaczenie, bo gdyby to nie miało znaczenia, nie można by przekazać =jako argumentu do programu (skąd ma wiedzieć, czy someprogram =działa someprogram, czy przypisać do zmiennej o nazwie someprogram?)
foo='one two three'; foo=$(for i in $foo; do echo -n "${i^} "; done) Mniejsza rozdzielczość dla każdego słowa. foo Now to „One Two Three”
vr286
Jak mogę zamienić pierwsze 3 lub 4 wielkie litery na wielkie? Jak PQRS-123-v1 do PQRS-123-v1 ? Albo możesz powiedzieć, wszystkie litery przed pierwszym myślnikiem ...
Vicky Dev
2
Alternatywne i czyste rozwiązanie zarówno dla Linuksa, jak i OSX, może być również używane ze zmiennymi bash
Co się stanie, jeśli pierwszy znak nie jest literą (ale tabulatorem, spacją i podwójnym cudzysłowem ze znakiem ucieczki)? Lepiej to przetestujmy , aż znajdziemy list! Więc:
Proszę napisać bardziej przejrzysty kod! brakuje ci cytatów w każdym miejscu. Używasz przestarzałej składni (lewych apostrofów); używasz przestarzałej składni ( $[...]). Używasz wielu bezużytecznych nawiasów. Zakładasz, że ciąg składa się ze znaków alfabetu łacińskiego (co powiesz na litery akcentowane lub litery z innych alfabetów?). Masz dużo pracy, aby uczynić ten fragment kodu użytecznym! (a ponieważ używasz wyrażenia regularnego, równie dobrze możesz użyć wyrażenia regularnego do znalezienia pierwszej litery zamiast pętli).
gniourf_gniourf
6
Myślę, że jesteś w błędzie. To obowiązkowy komentarz, który towarzyszy głosowaniu przeciw, wyjaśniając wszystkie niewłaściwe wzorce i błędne wyobrażenia o odpowiedzi. Proszę, ucz się na swoich błędach (a wcześniej spróbuj je zrozumieć) zamiast być upartym. Bycie dobrym człowiekiem jest również niezgodne z szerzeniem złych praktyk.
gniourf_gniourf
1
Lub, jeśli używasz Bash ≥4, nie potrzebujesz tr:if [[ $S =~ ^([^[:alpha:]]*)([[:alpha:]].*) ]]; then out=${BASH_REMATCH[1]}${BASH_REMATCH[2]^}; else out=$S; fi; printf '%s\n' "$out"
gniourf_gniourf
5
Ten kod jest nadal mocno uszkodzony. Nadal używa znaków odwrotnych zamiast nowoczesnej składni podstawiania; nadal ma niezrównane cytaty; nadal brakuje cudzysłowów w miejscach, w których mają one znaczenie ; itp. Spróbuj wstawić do danych testowych kilka znaków glob otoczonych białymi spacjami, jeśli nie uważasz, że te brakujące cudzysłowy mają znaczenie, i napraw problemy znalezione przez shellcheck.net, dopóki kod nie będzie czysty.
Charles Duffy
2
Jeśli chodzi o język, który zacytowałeś z unix.stackexchange.com/questions/68694/… , to brakuje ci tego, że echo $foojest to przykład sytuacji, w której parser oczekuje listy słów ; więc w twoim echo ${F}, zawartość Fjest dzielona na łańcuchy i rozszerzana globalnie. Podobnie jest w przypadku echo ${S:$N:1}przykładu i całej reszty. Zobacz BashPitfalls # 14 .
Odpowiedzi:
źródło
notQuiteCamel
sięNotQuiteCamel
. Twój wariant ma efekt uboczny lub zmusza pozostałe do małych liter - kosztem podwojenia liczby podpowłok i procesów tr.bash
.W jedną stronę z bash (wersja 4+):
wydruki:
źródło
"${foo,}"
. Aby wszystkie litery były małe, użyj"${foo,,}"
. Aby wszystkie litery były wielkie, użyj"${foo^^}"
.${foo~}
i${foo~~}
mam taki sam efekt jak${foo^}
i${foo^^}
. Ale nigdy nie widziałem tej alternatywy nigdzie wspomnianej.bad substitution
W jedną stronę z
sed
:Wydruki:
źródło
brew install coreutils gnu-sed
i postępuj zgodnie z instrukcjami, aby użyć poleceń bez prefiksug
. Na ile to warte, nigdy nie chciałem uruchamiać wersji tych poleceń dla OSX od czasu otrzymania wersji GNU.sed
w tym przypadku będziesz potrzebować GNUsed 's/./\U&/
i będzie działać na POSIX sed.źródło
Oto "natywne" narzędzia tekstowe:
źródło
tr [:lower:] [:upper:]
jest lepszym wyborem, jeśli musi działać w języku / ustawieniach regionalnych zawierających litery spoza zakresua-z
lubA-Z
.Używanie tylko awk
źródło
Można to zrobić również w czystym bashu z bash-3.2:
źródło
foo = $1
ale dostaję tylko-bash: foo: command not found
=
w zadaniach. To jest coś, co shellcheck.net znajdzie dla Ciebie programowo.=
jako argumentu do programu (skąd ma wiedzieć, czysomeprogram =
działasomeprogram
, czy przypisać do zmiennej o nazwiesomeprogram
?)To też działa ...
I tak dalej.
Źródła:
Wprowadzenie / samouczki:
źródło
Aby pisać wielką literą tylko pierwsze słowo:
Aby zapisać każde słowo w zmiennej wielką literą :
(działa w bash 4+)
źródło
foo='one two three'; foo=$(for i in $foo; do echo -n "${i^} "; done)
Mniejsza rozdzielczość dla każdego słowa. foo Now to „One Two Three”Alternatywne i czyste rozwiązanie zarówno dla Linuksa, jak i OSX, może być również używane ze zmiennymi bash
zwraca Abc
źródło
Ten pracował dla mnie:
Wyszukiwanie wszystkich plików * php w bieżącym katalogu i zamień pierwszy znak każdej nazwy pliku na wielką literę:
np .: test.php => Test.php
źródło
tylko dla zabawy, oto jesteś:
źródło
Nie dokładnie to, o co pytano, ale całkiem pomocne
I odwrotnie
źródło
first-letter-to-lower-xc () {v-first-letter-to-lower | xclip - schowek wyboru}
źródło
Co się stanie, jeśli pierwszy znak nie jest literą (ale tabulatorem, spacją i podwójnym cudzysłowem ze znakiem ucieczki)? Lepiej to przetestujmy , aż znajdziemy list! Więc:
źródło
$[...]
). Używasz wielu bezużytecznych nawiasów. Zakładasz, że ciąg składa się ze znaków alfabetu łacińskiego (co powiesz na litery akcentowane lub litery z innych alfabetów?). Masz dużo pracy, aby uczynić ten fragment kodu użytecznym! (a ponieważ używasz wyrażenia regularnego, równie dobrze możesz użyć wyrażenia regularnego do znalezienia pierwszej litery zamiast pętli).tr
:if [[ $S =~ ^([^[:alpha:]]*)([[:alpha:]].*) ]]; then out=${BASH_REMATCH[1]}${BASH_REMATCH[2]^}; else out=$S; fi; printf '%s\n' "$out"
echo $foo
jest to przykład sytuacji, w której parser oczekuje listy słów ; więc w twoimecho ${F}
, zawartośćF
jest dzielona na łańcuchy i rozszerzana globalnie. Podobnie jest w przypadkuecho ${S:$N:1}
przykładu i całej reszty. Zobacz BashPitfalls # 14 .