Có cách nào trong bash để chuyển đổi một chuỗi thành một chuỗi chữ thường không?
Ví dụ: nếu tôi có:
a="Hi all"
Tôi muốn chuyển đổi nó thành:
"hi all"
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
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 thuộc tính declare
, hãy 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 tùy chọn declare
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.
Chỉnh sửa:
Đã thêm "chuyển đổi ký tự đầu tiên bằng Word" (${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.
echo "Hi All" | tr "[:upper:]" "[:lower:]"
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ó nghĩa là bash
nhưng nếu bạn có thể sử dụng zsh
thì dễ như
b=$a:l
cho chữ thường và
b=$a:u
cho chữ hoa.
Trong zsh:
echo $a:u
Phải yêu zsh!
Sử dụng GNU sed
:
sed 's/.*/\L&/'
Thí dụ:
$ foo="Some STRIng";
$ foo=$(echo "$foo" | sed 's/.*/\L&/')
$ echo "$foo"
some string
Đối với Shell tiêu chuẩn (không có bashism) chỉ sử dụng nội trang:
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}"
}
Tiền Bash 4.0
Bash Hạ trường hợp của chuỗi và gán cho biến
VARIABLE=$(echo "$VARIABLE" | tr '[:upper:]' '[:lower:]')
echo "$VARIABLE"
Trong bash 4, bạn có thể sử dụng sắp chữ
Thí dụ:
A="HELLO WORLD"
typeset -l A=$A
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 cho riêng mình 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 bạn, 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. Nó là một sửa chữa 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ẽ.
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/
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, echos và các tập tin tạm thời để lấy các biến tầm thường. Điều này hoạt động rất tốt đối với 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
Đơn giản Kiểu chữ C cho vòng lặp để lặp qua các chuỗi . Đối với dòng bên dưới nếu bạn chưa thấy bất cứ điều gì như thế này trước đây đâ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}}"
Đố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 fork/exec 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.
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.Nhiều câu trả lời sử dụng các chương trình bên ngoài, 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 ký hiệu ${VAR,,}
(thật dễ dàng và thú vị). Đố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 phiên bản chữ thường. Tôi đã đọc các nhận xét về việc đặt kết quả thành một var, nhưng điều đó không thực sự khả chuyển trong 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)"
.
Cách thức hoạt động
Cách thức hoạt động này 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
một lần nữa để chuyển đổi số trở lại thành char. Từ 'A' -to-> 'a'
chúng ta có chênh lệch 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="[email protected]"
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="[email protected]"
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 "[email protected]" 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ỉ hoạt động đối với các ký tự ASCII .
Đối với tôi điều đó là tốt, vì tôi biết tôi sẽ chỉ chuyển ASCII ký tự 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.
Nếu bạn thích python và có tùy chọn cài đặt gói python mới, bạn có thể thử tiện ích python này .
# install pythonp
$ pip install pythonp
$ echo $a | pythonp "l.lower()"
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 a-z 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 a-z thành A-Z
Để 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 &&^&& #@[email protected]%%& KAR2~THIK
Để lưu trữ chuỗi biến đổi thành một biến. Theo dõi làm việc cho tôi -$SOURCE_NAME
đến $TARGET_NAME
TARGET_NAME="`echo $SOURCE_NAME | tr '[:upper:]' '[:lower:]'`"
Đâ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 phương pháp của mình.
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
thành chữ thường; 4s cho chữ hoaDung dịch:
#!/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 bằng các ký tự bổ sung