Câu trả lời:
Có nhiều cách khác nhau:
$ echo "$a" | tr '[:upper:]' '[:lower:]'
hi all
$ echo "$a" | awk '{print tolower($0)}'
hi all
Bạn có thể gặp phải các vấn đề về tính di động với các ví dụ sau:
$ echo "${a,,}"
hi all
$ echo "$a" | sed -e 's/\(.*\)/\L\1/'
hi all
# this also works:
$ sed -e 's/\(.*\)/\L\1/' <<< "$a"
hi all
$ echo "$a" | perl -ne 'print lc'
hi all
lc(){
case "$1" in
[A-Z])
n=$(printf "%d" "'$1")
n=$((n+32))
printf \\$(printf "%o" "$n")
;;
*)
printf "%s" "$1"
;;
esac
}
word="I Love Bash"
for((i=0;i<${#word};i++))
do
ch="${word:$i:1}"
lc "$ch"
done
Lưu ý: YMMV trên cái này. Không hoạt động đối với tôi (GNU bash phiên bản 4.2.46 và 4.0.33 (và hành vi tương tự 2.05b.0 nhưng nocasematch không được triển khai)) ngay cả khi sử dụng shopt -u nocasematch;
. Bỏ đặt rằng nocasematch gây ra [["fooBaR" == "FOObar"]] khớp với NHƯNG trong trường hợp kỳ lạ [bz] được khớp không chính xác bởi [AZ]. Bash bị nhầm lẫn bởi tiêu cực kép ("unet nocasematch")! :-)
word="Hi All"
như các ví dụ khác, nó sẽ trả về ha
, không hi all
. Nó chỉ hoạt động cho các chữ cái viết hoa và bỏ qua các chữ cái đã được hạ thấp.
tr
và awk
được chỉ định trong tiêu chuẩn POSIX.
tr '[:upper:]' '[:lower:]'
sẽ sử dụng ngôn ngữ hiện tại để xác định chữ hoa / chữ thường, do đó, nó sẽ hoạt động với các ngôn ngữ sử dụng các chữ cái có dấu phụ.
b="$(echo $a | tr '[A-Z]' '[a-z]')"
Trong Bash 4:
Để viết thường
$ string="A FEW WORDS"
$ echo "${string,}"
a FEW WORDS
$ echo "${string,,}"
a few words
$ echo "${string,,[AEIUO]}"
a FeW WoRDS
$ string="A Few Words"
$ declare -l string
$ string=$string; echo "$string"
a few words
Đến trường hợp trên
$ string="a few words"
$ echo "${string^}"
A few words
$ echo "${string^^}"
A FEW WORDS
$ echo "${string^^[aeiou]}"
A fEw wOrds
$ string="A Few Words"
$ declare -u string
$ string=$string; echo "$string"
A FEW WORDS
Chuyển đổi (không có giấy tờ, nhưng có thể cấu hình tùy chọn tại thời điểm biên dịch)
$ string="A Few Words"
$ echo "${string~~}"
a fEW wORDS
$ string="A FEW WORDS"
$ echo "${string~}"
a FEW WORDS
$ string="a few words"
$ echo "${string~}"
A few words
Viết hoa (không có giấy tờ, nhưng có thể cấu hình tùy chọn tại thời điểm biên dịch)
$ string="a few words"
$ declare -c string
$ string=$string
$ echo "$string"
A few words
Trường hợp tiêu đề:
$ string="a few words"
$ string=($string)
$ string="${string[@]^}"
$ echo "$string"
A Few Words
$ declare -c string
$ string=(a few words)
$ echo "${string[@]}"
A Few Words
$ string="a FeW WOrdS"
$ string=${string,,}
$ string=${string~}
$ echo "$string"
A few words
Để tắt một declare
thuộc tính, sử dụng +
. Ví dụ , declare +c string
. Điều này ảnh hưởng đến các bài tập tiếp theo và không phải giá trị hiện tại.
Các declare
tùy chọn thay đổi thuộc tính của biến, nhưng không thay đổi nội dung. Việc đánh giá lại trong các ví dụ của tôi cập nhật nội dung để hiển thị các thay đổi.
Biên tập:
Đã thêm "chuyển đổi ký tự đầu tiên bằng từ" ( ${var~}
) theo đề xuất của ghostdog74 .
Chỉnh sửa: Sửa hành vi dấu ngã để khớp với Bash 4.3.
string="łódź"; echo ${string~~}
sẽ trả về "ŁÓDŹ", nhưng echo ${string^^}
trả về "łóDź". Ngay cả trong LC_ALL=pl_PL.utf-8
. Đó là sử dụng bash 4.2.24.
en_US.UTF-8
. Đó là một lỗi và tôi đã báo cáo nó.
echo "$string" | tr '[:lower:]' '[:upper:]'
. Nó có thể sẽ thể hiện sự thất bại tương tự. Vì vậy, vấn đề ít nhất là một phần không phải của Bash.
echo "Hi All" | tr "[:upper:]" "[:lower:]"
tr
không hoạt động đối với tôi đối với các nhân vật không phải ACII. Tôi có tập tin miền địa phương chính xác và tập tin miền địa phương được tạo. Có ai biết tôi có thể làm gì sai không?
[:upper:]
cần thiết?
a="$(tr [A-Z] [a-z] <<< "$a")"
{ print tolower($0) }
y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
a="$(tr [A-Z] [a-z] <<< "$a")"
vẻ dễ nhất đối với tôi. Tôi vẫn là người mới bắt đầu ...
sed
giải pháp; Tôi đã làm việc trong một môi trường mà vì một số lý do không có tr
nhưng tôi vẫn chưa tìm thấy một hệ thống mà không có sed
, cộng với rất nhiều thời gian tôi muốn làm điều này Tôi đã làm một cái gì đó khác bằng sed
mọi cách để có thể xâu chuỗi các lệnh cùng nhau thành một câu lệnh (dài).
tr [A-Z] [a-z] A
, shell có thể thực hiện mở rộng tên tệp nếu có tên tệp bao gồm một chữ cái hoặc nullgob được đặt. tr "[A-Z]" "[a-z]" A
sẽ cư xử đúng mực.
sed
tr [A-Z] [a-z]
không chính xác ở hầu hết các địa phương. ví dụ, trong en-US
miền địa phương, A-Z
thực sự là khoảng AaBbCcDdEeFfGgHh...XxYyZ
.
Tôi biết đây là một bài viết cũ nhưng tôi đã đưa ra câu trả lời này cho một trang web khác vì vậy tôi nghĩ rằng tôi đã đăng nó lên đây:
LỚN -> thấp hơn : sử dụng python:
b=`echo "print '$a'.lower()" | python`
Hoặc Ruby:
b=`echo "print '$a'.downcase" | ruby`
Hoặc Perl (có lẽ là sở thích của tôi):
b=`perl -e "print lc('$a');"`
Hoặc PHP:
b=`php -r "print strtolower('$a');"`
Hoặc Awk:
b=`echo "$a" | awk '{ print tolower($1) }'`
Hoặc Sed:
b=`echo "$a" | sed 's/./\L&/g'`
Hoặc Bash 4:
b=${a,,}
Hoặc NodeJS nếu bạn có nó (và có một chút hạt dẻ ...):
b=`echo "console.log('$a'.toLowerCase());" | node`
Bạn cũng có thể sử dụng dd
(nhưng tôi sẽ không!):
b=`echo "$a" | dd conv=lcase 2> /dev/null`
thấp hơn -> LỚN :
sử dụng trăn:
b=`echo "print '$a'.upper()" | python`
Hoặc Ruby:
b=`echo "print '$a'.upcase" | ruby`
Hoặc Perl (có lẽ là sở thích của tôi):
b=`perl -e "print uc('$a');"`
Hoặc PHP:
b=`php -r "print strtoupper('$a');"`
Hoặc Awk:
b=`echo "$a" | awk '{ print toupper($1) }'`
Hoặc Sed:
b=`echo "$a" | sed 's/./\U&/g'`
Hoặc Bash 4:
b=${a^^}
Hoặc NodeJS nếu bạn có nó (và có một chút hạt dẻ ...):
b=`echo "console.log('$a'.toUpperCase());" | node`
Bạn cũng có thể sử dụng dd
(nhưng tôi sẽ không!):
b=`echo "$a" | dd conv=ucase 2> /dev/null`
Ngoài ra khi bạn nói 'shell' tôi giả sử bạn có ý bash
nhưng nếu bạn có thể sử dụng zsh
nó dễ như
b=$a:l
cho chữ thường và
b=$a:u
cho chữ hoa
a
chứa một trích dẫn, bạn không chỉ có hành vi bị hỏng mà còn gặp sự cố bảo mật nghiêm trọng.
Trong zsh:
echo $a:u
Phải yêu zsh!
echo ${(C)a} #Upcase the first char only
Tiền Bash 4.0
Bash Hạ trường hợp của một chuỗi và gán cho biến
VARIABLE=$(echo "$VARIABLE" | tr '[:upper:]' '[:lower:]')
echo "$VARIABLE"
echo
và đường ống: sử dụng$(tr '[:upper:]' '[:lower:]' <<<"$VARIABLE")
Đối với hệ vỏ tiêu chuẩn (không có bashism) chỉ sử dụng nội dung:
uppers=ABCDEFGHIJKLMNOPQRSTUVWXYZ
lowers=abcdefghijklmnopqrstuvwxyz
lc(){ #usage: lc "SOME STRING" -> "some string"
i=0
while ([ $i -lt ${#1} ]) do
CUR=${1:$i:1}
case $uppers in
*$CUR*)CUR=${uppers%$CUR*};OUTPUT="${OUTPUT}${lowers:${#CUR}:1}";;
*)OUTPUT="${OUTPUT}$CUR";;
esac
i=$((i+1))
done
echo "${OUTPUT}"
}
Và cho chữ hoa:
uc(){ #usage: uc "some string" -> "SOME STRING"
i=0
while ([ $i -lt ${#1} ]) do
CUR=${1:$i:1}
case $lowers in
*$CUR*)CUR=${lowers%$CUR*};OUTPUT="${OUTPUT}${uppers:${#CUR}:1}";;
*)OUTPUT="${OUTPUT}$CUR";;
esac
i=$((i+1))
done
echo "${OUTPUT}"
}
${var:1:1}
là một Bashism.
Bạn có thể thử cái này
s="Hello World!"
echo $s # Hello World!
a=${s,,}
echo $a # hello world!
b=${s^^}
echo $b # HELLO WORLD!
ref: http://wiki.workrame.com/shell-script-convert-text-to-lowercase-and-uppercase/
Tôi muốn nhận tín dụng cho lệnh tôi muốn chia sẻ nhưng sự thật là tôi đã nhận được nó để sử dụng từ http://commandlinefu.com . Nó có lợi thế là nếu bạn cd
vào bất kỳ thư mục nào trong thư mục nhà riêng của mình, nó sẽ thay đổi tất cả các tệp và thư mục thành chữ thường, vui lòng sử dụng một cách thận trọng. Đây là một sửa lỗi dòng lệnh tuyệt vời và đặc biệt hữu ích cho vô số album bạn đã lưu trữ trên ổ đĩa của bạn.
find . -depth -exec rename 's/(.*)\/([^\/]*)/$1\/\L$2/' {} \;
Bạn có thể chỉ định một thư mục thay cho dấu chấm (.) Sau khi tìm thấy biểu thị thư mục hiện tại hoặc đường dẫn đầy đủ.
Tôi hy vọng giải pháp này chứng minh hữu ích một điều mà lệnh này không làm là thay thế khoảng trắng bằng dấu gạch dưới - có lẽ một lần khác có lẽ.
prename
từ perl
: dpkg -S "$(readlink -e /usr/bin/rename)"
choperl: /usr/bin/prename
Nhiều câu trả lời sử dụng các chương trình bên ngoài, mà không thực sự sử dụng Bash
.
Nếu bạn biết bạn sẽ có sẵn Bash4, bạn thực sự chỉ nên sử dụng ${VAR,,}
ký hiệu (nó rất dễ dàng và tuyệt vời). Đối với Bash trước 4 (Mac của tôi vẫn sử dụng Bash 3.2 chẳng hạn). Tôi đã sử dụng phiên bản sửa của câu trả lời của @ ghostdog74 để tạo phiên bản di động hơn.
Một bạn có thể gọi lowercase 'my STRING'
và nhận được một phiên bản chữ thường. Tôi đọc các bình luận về việc đặt kết quả thành một var, nhưng điều đó không thực sự di động Bash
, vì chúng tôi không thể trả về chuỗi. In nó là giải pháp tốt nhất. Dễ dàng chụp với một cái gì đó như var="$(lowercase $str)"
.
Làm thế nào điều này hoạt động
Cách thức này hoạt động là bằng cách lấy đại diện số nguyên ASCII của mỗi char với printf
và sau đó adding 32
nếu upper-to->lower
, hoặc subtracting 32
nếu lower-to->upper
. Sau đó sử dụng printf
lại để chuyển đổi số trở lại thành char. Từ 'A' -to-> 'a'
chúng tôi có một sự khác biệt của 32 ký tự.
Sử dụng printf
để giải thích:
$ printf "%d\n" "'a"
97
$ printf "%d\n" "'A"
65
97 - 65 = 32
Và đây là phiên bản làm việc với các ví dụ.
Xin lưu ý các ý kiến trong mã, vì chúng giải thích rất nhiều thứ:
#!/bin/bash
# lowerupper.sh
# Prints the lowercase version of a char
lowercaseChar(){
case "$1" in
[A-Z])
n=$(printf "%d" "'$1")
n=$((n+32))
printf \\$(printf "%o" "$n")
;;
*)
printf "%s" "$1"
;;
esac
}
# Prints the lowercase version of a sequence of strings
lowercase() {
word="$@"
for((i=0;i<${#word};i++)); do
ch="${word:$i:1}"
lowercaseChar "$ch"
done
}
# Prints the uppercase version of a char
uppercaseChar(){
case "$1" in
[a-z])
n=$(printf "%d" "'$1")
n=$((n-32))
printf \\$(printf "%o" "$n")
;;
*)
printf "%s" "$1"
;;
esac
}
# Prints the uppercase version of a sequence of strings
uppercase() {
word="$@"
for((i=0;i<${#word};i++)); do
ch="${word:$i:1}"
uppercaseChar "$ch"
done
}
# The functions will not add a new line, so use echo or
# append it if you want a new line after printing
# Printing stuff directly
lowercase "I AM the Walrus!"$'\n'
uppercase "I AM the Walrus!"$'\n'
echo "----------"
# Printing a var
str="A StRing WITH mixed sTUFF!"
lowercase "$str"$'\n'
uppercase "$str"$'\n'
echo "----------"
# Not quoting the var should also work,
# since we use "$@" inside the functions
lowercase $str$'\n'
uppercase $str$'\n'
echo "----------"
# Assigning to a var
myLowerVar="$(lowercase $str)"
myUpperVar="$(uppercase $str)"
echo "myLowerVar: $myLowerVar"
echo "myUpperVar: $myUpperVar"
echo "----------"
# You can even do stuff like
if [[ 'option 2' = "$(lowercase 'OPTION 2')" ]]; then
echo "Fine! All the same!"
else
echo "Ops! Not the same!"
fi
exit 0
Và kết quả sau khi chạy này:
$ ./lowerupper.sh
i am the walrus!
I AM THE WALRUS!
----------
a string with mixed stuff!
A STRING WITH MIXED STUFF!
----------
a string with mixed stuff!
A STRING WITH MIXED STUFF!
----------
myLowerVar: a string with mixed stuff!
myUpperVar: A STRING WITH MIXED STUFF!
----------
Fine! All the same!
Điều này chỉ nên làm việc cho các ký tự ASCII .
Đối với tôi điều đó là tốt, vì tôi biết tôi sẽ chỉ truyền ký tự ASCII cho nó.
Tôi đang sử dụng điều này cho một số tùy chọn CLI không phân biệt chữ hoa chữ thường.
Trường hợp chuyển đổi được thực hiện cho chỉ bảng chữ cái. Vì vậy, điều này nên làm việc gọn gàng.
Tôi đang tập trung vào việc chuyển đổi bảng chữ cái giữa az từ chữ hoa sang chữ thường. Bất kỳ ký tự nào khác chỉ nên được in ở thiết bị xuất chuẩn vì nó là ...
Chuyển đổi tất cả văn bản trong đường dẫn / thành / tệp / tên tệp trong phạm vi az thành AZ
Để chuyển đổi chữ thường thành chữ hoa
cat path/to/file/filename | tr 'a-z' 'A-Z'
Để chuyển đổi từ chữ hoa sang chữ thường
cat path/to/file/filename | tr 'A-Z' 'a-z'
Ví dụ,
tên tệp:
my name is xyz
được chuyển đổi thành:
MY NAME IS XYZ
Ví dụ 2:
echo "my name is 123 karthik" | tr 'a-z' 'A-Z'
# Output:
# MY NAME IS 123 KARTHIK
Ví dụ 3:
echo "my name is 123 &&^&& #@$#@%%& kAR2~thik" | tr 'a-z' 'A-Z'
# Output:
# MY NAME IS 123 &&^&& #@0@%%& KAR2~THIK
Nếu sử dụng v4, đây là nướng trong . Nếu không, đây là một giải pháp đơn giản, áp dụng rộng rãi . Các câu trả lời khác (và nhận xét) về chủ đề này khá hữu ích trong việc tạo mã bên dưới.
# Like echo, but converts to lowercase
echolcase () {
tr [:upper:] [:lower:] <<< "${*}"
}
# Takes one arg by reference (var name) and makes it lowercase
lcase () {
eval "${1}"=\'$(echo ${!1//\'/"'\''"} | tr [:upper:] [:lower:] )\'
}
Ghi chú:
a="Hi All"
và sau đó: lcase a
sẽ làm điều tương tự như:a=$( echolcase "Hi All" )
${!1//\'/"'\''"}
thay vì ${!1}
cho phép điều này hoạt động ngay cả khi chuỗi có dấu ngoặc kép.Đối với các phiên bản Bash sớm hơn 4.0, phiên bản này phải nhanh nhất (vì nó không rẽ nhánh / thực thi bất kỳ lệnh nào):
function string.monolithic.tolower
{
local __word=$1
local __len=${#__word}
local __char
local __octal
local __decimal
local __result
for (( i=0; i<__len; i++ ))
do
__char=${__word:$i:1}
case "$__char" in
[A-Z] )
printf -v __decimal '%d' "'$__char"
printf -v __octal '%03o' $(( $__decimal ^ 0x20 ))
printf -v __char \\$__octal
;;
esac
__result+="$__char"
done
REPLY="$__result"
}
Câu trả lời của Technosaurus cũng có tiềm năng, mặc dù nó đã chạy đúng cho mee.
Mặc dù câu hỏi này bao nhiêu tuổi và tương tự như câu trả lời này của Technosaurus . Tôi đã có một thời gian khó khăn để tìm một giải pháp di động trên hầu hết các nền tảng (That I Use) cũng như các phiên bản bash cũ hơn. Tôi cũng đã thất vọng với các mảng, chức năng và sử dụng các bản in, tiếng vang và các tập tin tạm thời để lấy các biến tầm thường. Điều này làm việc rất tốt cho tôi cho đến nay tôi nghĩ rằng tôi sẽ chia sẻ. Môi trường thử nghiệm chính của tôi là:
- GNU bash, phiên bản 4.1.2 (1) -release (x86_64-redhat-linux-gnu)
- GNU bash, phiên bản 3.2.57 (1) -release (sparc-sun-solaris2.10)
lcs="abcdefghijklmnopqrstuvwxyz"
ucs="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
input="Change Me To All Capitals"
for (( i=0; i<"${#input}"; i++ )) ; do :
for (( j=0; j<"${#lcs}"; j++ )) ; do :
if [[ "${input:$i:1}" == "${lcs:$j:1}" ]] ; then
input="${input/${input:$i:1}/${ucs:$j:1}}"
fi
done
done
Kiểu C đơn giản cho vòng lặp để lặp qua các chuỗi. Đối với dòng dưới đây nếu bạn chưa thấy bất cứ điều gì như thế này trước đây là nơi tôi đã học được điều này . Trong trường hợp này, dòng kiểm tra xem char $ {input: $ i: 1} (chữ thường) có tồn tại trong đầu vào không và nếu có thì thay thế nó bằng char $ {ucs: $ j: 1} (chữ hoa) và lưu trữ nó trở lại đầu vào.
input="${input/${input:$i:1}/${ucs:$j:1}}"
Đây là một biến thể nhanh hơn nhiều của cách tiếp cận của JaredTS486 , sử dụng các khả năng Bash gốc (bao gồm các phiên bản Bash <4.0) để tối ưu hóa cách tiếp cận của anh ta.
Tôi đã hẹn giờ 1.000 lần lặp của phương pháp này cho một chuỗi nhỏ (25 ký tự) và một chuỗi lớn hơn (445 ký tự), cho cả chuyển đổi chữ thường và chữ hoa. Vì các chuỗi kiểm tra chủ yếu là chữ thường, chuyển đổi sang chữ thường thường nhanh hơn chữ hoa.
Tôi đã so sánh cách tiếp cận của mình với một số câu trả lời khác trên trang này tương thích với Bash 3.2. Cách tiếp cận của tôi hiệu quả hơn nhiều so với hầu hết các cách tiếp cận được ghi lại ở đây, và thậm chí còn nhanh hơn tr
trong một số trường hợp.
Dưới đây là kết quả thời gian cho 1.000 lần lặp gồm 25 ký tự:
tr
để viết thường; 3,81s cho chữ hoaKết quả thời gian cho 1.000 lần lặp của 445 ký tự (bao gồm bài thơ "The Robin" của Witter Bynner):
tr
chữ thường; 4s cho chữ hoaGiải pháp:
#!/bin/bash
set -e
set -u
declare LCS="abcdefghijklmnopqrstuvwxyz"
declare UCS="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
function lcase()
{
local TARGET="${1-}"
local UCHAR=''
local UOFFSET=''
while [[ "${TARGET}" =~ ([A-Z]) ]]
do
UCHAR="${BASH_REMATCH[1]}"
UOFFSET="${UCS%%${UCHAR}*}"
TARGET="${TARGET//${UCHAR}/${LCS:${#UOFFSET}:1}}"
done
echo -n "${TARGET}"
}
function ucase()
{
local TARGET="${1-}"
local LCHAR=''
local LOFFSET=''
while [[ "${TARGET}" =~ ([a-z]) ]]
do
LCHAR="${BASH_REMATCH[1]}"
LOFFSET="${LCS%%${LCHAR}*}"
TARGET="${TARGET//${LCHAR}/${UCS:${#LOFFSET}:1}}"
done
echo -n "${TARGET}"
}
Cách tiếp cận rất đơn giản: trong khi chuỗi đầu vào có bất kỳ chữ cái in hoa nào còn lại, hãy tìm cái tiếp theo và thay thế tất cả các trường hợp của chữ cái đó bằng biến thể chữ thường của nó. Lặp lại cho đến khi tất cả các chữ cái viết hoa được thay thế.
Một số đặc điểm hiệu suất của giải pháp của tôi:
UCS
và LCS
có thể được tăng thêm với các ký tự bổ sung