هل هناك طريقة في bash لتحويل سلسلة إلى سلسلة أحرف صغيرة؟
على سبيل المثال ، إذا كان لدي:
a="Hi all"
أريد تحويله إلى:
"hi all"
الطرق المختلفة:
$ echo "$a" | tr '[:upper:]' '[:lower:]'
hi all
$ echo "$a" | awk '{print tolower($0)}'
hi all
قد تواجه مشكلات قابلية الحمل في الأمثلة التالية:
$ 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
ملاحظة: YMMV على هذا واحد. لا يعمل من أجلي (إصدار GNU bash 4.2.46 و 4.0.33 (ونفس السلوك 2.05b.0 ولكن nocasematch لم يتم تنفيذه)) حتى باستخدام shopt -u nocasematch;
. يؤدي إلغاء تعيين nocasematch إلى [["fooBaR" == "FOObar"]] لمطابقة "OK BUT" داخل الحالة الغريبة [b-z] بشكل غير صحيح بواسطة [A-Z]. يتم الخلط بين باش من قبل السلبية المزدوجة ("إلغاء nocasematch")! :-)
في باش 4:
إلى أحرف صغيرة
$ 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
إلى الحالة العليا
$ 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
تبديل (بدون وثائق ، ولكن قابل للتكوين اختياريًا في وقت الترجمة)
$ 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
الكتابة بالأحرف الكبيرة (غير موثقة ، لكن قابلة للتكوين اختياريًا في وقت الترجمة)
$ string="a few words"
$ declare -c string
$ string=$string
$ echo "$string"
A few words
حالة العنوان:
$ 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
لإيقاف تشغيل سمة declare
، استخدم +
. على سبيل المثال ، declare +c string
. هذا يؤثر على التعيينات اللاحقة وليس على القيمة الحالية.
تغير الخيارات declare
سمة المتغير ، لكن لا تغير المحتويات. تقوم عمليات إعادة التعيين في أمثلةي بتحديث المحتويات لإظهار التغييرات.
تصحيح:
تمت إضافة "تبديل الحرف الأول بواسطة Word" (${var~}
) وفقًا لما اقترحه ghostdog74 .
تحرير: تصحيح سلوك تيلدا لمطابقة Bash 4.3.
echo "Hi All" | tr "[:upper:]" "[:lower:]"
أعلم أن هذا منشور قديم ، لكنني قدمت هذه الإجابة لموقع آخر ، لذا اعتقدت أنني قمت بنشره هنا:
UPPER -> أقل : استخدام الثعبان:
b=`echo "print '$a'.lower()" | python`
أو روبي:
b=`echo "print '$a'.downcase" | Ruby`
أو بيرل (ربما المفضل لدي):
b=`Perl -e "print lc('$a');"`
أو PHP:
b=`php -r "print strtolower('$a');"`
أو اوك:
b=`echo "$a" | awk '{ print tolower($1) }'`
أو سيد:
b=`echo "$a" | sed 's/./\L&/g'`
أو باش 4:
b=${a,,}
أو NodeJS إذا كان لديك (وقليلًا من المكسرات ...):
b=`echo "console.log('$a'.toLowerCase());" | node`
يمكنك أيضًا استخدام dd
(لكنني لن أفعل!):
b=`echo "$a" | dd conv=lcase 2> /dev/null`
أقل -> UPPER :
استخدام الثعبان:
b=`echo "print '$a'.upper()" | python`
أو روبي:
b=`echo "print '$a'.upcase" | Ruby`
أو بيرل (ربما المفضل لدي):
b=`Perl -e "print uc('$a');"`
أو PHP:
b=`php -r "print strtoupper('$a');"`
أو اوك:
b=`echo "$a" | awk '{ print toupper($1) }'`
أو سيد:
b=`echo "$a" | sed 's/./\U&/g'`
أو باش 4:
b=${a^^}
أو NodeJS إذا كان لديك (وقليلًا من المكسرات ...):
b=`echo "console.log('$a'.toUpperCase());" | node`
يمكنك أيضًا استخدام dd
(لكنني لن أفعل!):
b=`echo "$a" | dd conv=ucase 2> /dev/null`
أيضًا عندما تقول "Shell" ، فأنا أفترض أنك تقصد bash
ولكن إذا كنت تستطيع استخدام zsh
فسيكون الأمر سهلاً
b=$a:l
لحالة أقل و
b=$a:u
لحالة العلوي.
في zsh:
echo $a:u
فلدي الحب zsh!
باستخدام GNU sed
:
sed 's/.*/\L&/'
مثال:
$ foo="Some STRIng";
$ foo=$(echo "$foo" | sed 's/.*/\L&/')
$ echo "$foo"
some string
قبل باش 4.0
باش خفض حالة سلسلة وتعيين متغير
VARIABLE=$(echo "$VARIABLE" | tr '[:upper:]' '[:lower:]')
echo "$VARIABLE"
بالنسبة إلى Shell قياسي (بدون bashism) باستخدام مدخلات فقط:
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}"
}
وللحالة العليا:
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}"
}
في باش 4 يمكنك استخدام typet
مثال:
A="HELLO WORLD"
typeset -l A=$A
أرغب في الحصول على رصيد للأمر الذي أود مشاركته ولكن الحقيقة هي أنني حصلت عليه للاستخدام الخاص من http://commandlinefu.com . له ميزة أنه إذا كنت cd
إلى أي دليل داخل المجلد الرئيسي الخاص بك ، فسيتم تغيير جميع الملفات والمجلدات إلى الحالة الصغيرة بشكل متكرر ، يرجى استخدام بحذر. إنه إصلاح رائع لسطر الأوامر ومفيد بشكل خاص لأعداد الألبومات المتعددة التي قمت بتخزينها على محرك الأقراص.
find . -depth -exec rename 's/(.*)\/([^\/]*)/$1\/\L$2/' {} \;
يمكنك تحديد دليل بدلاً من النقطة (.) بعد البحث الذي يشير إلى الدليل الحالي أو المسار الكامل.
آمل أن يكون هذا الحل مفيدًا لأن الشيء الوحيد الذي لا تفعله هذه الأوامر هو استبدال المسافات بالشرطات السفلية - حسناً في وقت آخر ربما.
يمكنك تجربة هذا
s="Hello World!"
echo $s # Hello World!
a=${s,,}
echo $a # hello world!
b=${s^^}
echo $b # HELLO WORLD!
المرجع: http://wiki.workassis.com/Shell-script-convert-text-to-lowercase-and-uppercase/
على الرغم من كم عمر هذا السؤال ومشابه بـ هذه الإجابة من قبل technosaurus . واجهت صعوبة في إيجاد حل كان قابلاً للنقل عبر معظم الأنظمة الأساسية (التي أستخدمها) بالإضافة إلى الإصدارات القديمة من bash. لقد أصبت بالإحباط من المصفوفات والوظائف واستخدام المطبوعات والأصداء والملفات المؤقتة لاسترداد المتغيرات التافهة. هذا يعمل بشكل جيد للغاية بالنسبة لي حتى الآن اعتقدت أنني سوف أشارك. بيئات الاختبار الرئيسية هي:
- نسخة GNU bash ، الإصدار 4.1.2 (1) - الإصدار (x86_64-redhat-linux-gnu)
- غنو باش ، الإصدار 3.2.57 (1) - إصدار (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
بسيط نمط C للحلقة للتكرار من خلال الأوتار. بالنسبة للسطر أدناه ، إذا لم ترَ شيئًا كهذا من قبل فهذا هو المكان الذي تعلمت فيه هذا . في هذه الحالة ، يتحقق السطر مما إذا كان char $ {input: $ i: 1} (الأحرف الصغيرة) موجودًا في الإدخال وإذا كان الأمر كذلك يستبدله بـ char $ {ucs: $ j: 1} (الحالة العلوية) ويخزنها العودة إلى المدخلات.
input="${input/${input:$i:1}/${ucs:$j:1}}"
بالنسبة إلى إصدارات Bash الأقدم من 4.0 ، يجب أن يكون هذا الإصدار هو الأسرع (حيث لا fork/exec أي أوامر):
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"
}
إجابة technosaurus كانت تنطوي على إمكانات أيضًا ، على الرغم من أنها كانت تعمل بشكل صحيح في mee.
إذا كنت تستخدم الإصدار v4 ، فسيكون هذا مخبوزًا . إذا لم يكن الأمر كذلك ، فإليك حل بسيط وقابل للتطبيق على نطاق واسع حل. كانت الإجابات (والتعليقات) الأخرى على هذا الموضوع مفيدة للغاية في إنشاء الكود أدناه.
# 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:] )\'
}
ملاحظات:
a="Hi All"
ثم: lcase a
ستفعل نفس الشيء مثل: a=$( echolcase "Hi All" )
${!1//\'/"'\''"}
بدلاً من ${!1}
يسمح لهذا بالعمل حتى إذا كانت السلسلة بها علامات اقتباس.العديد من الإجابات باستخدام برامج خارجية ، والتي لا تستخدم بالفعل Bash
.
إذا كنت تعرف أنك ستتوفر Bash4 ، فعليك فقط استخدام رمز ${VAR,,}
(إنه سهل وبارد). بالنسبة إلى Bash قبل 4 (لا يزال My Mac يستخدم Bash 3.2 على سبيل المثال). لقد استخدمت الإصدار الصحيح من إجابة @ ghostdog74 لإنشاء نسخة محمولة أكثر.
يمكنك الاتصال بـ lowercase 'my STRING'
واحصل على إصدار صغير. قرأت تعليقات حول تعيين النتيجة إلى var ، لكن ذلك ليس قابلاً للنقل في Bash
، نظرًا لأننا لا نستطيع إرجاع السلاسل. طباعته هو الحل الأفضل. من السهل التقاطها مع شيء مثل var="$(lowercase $str)"
.
كيف يعمل هذا
الطريقة التي يتم بها ذلك هي الحصول على [عدد صحيح] ASCII تمثيل صحيح لكل حرف بـ printf
ثم adding 32
إذا upper-to->lower
أو subtracting 32
if lower-to->upper
. ثم استخدم printf
مرة أخرى لتحويل الرقم مرة أخرى إلى حرف char. من 'A' -to-> 'a'
لدينا فرق من 32 حرفًا.
باستخدام printf
لشرح:
$ printf "%d\n" "'a"
97
$ printf "%d\n" "'A"
65
97 - 65 = 32
وهذه هي النسخة العاملة مع الأمثلة.
يرجى ملاحظة التعليقات في الكود ، لأنها توضح الكثير من الأشياء:
#!/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
والنتائج بعد تشغيل هذا:
$ ./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!
يجب أن يعمل هذا فقط من أجل ASCII أحرف بالرغم .
بالنسبة لي ، لا بأس ، بما أنني أعلم أنني سأمررها ASCII فقط.
أنا أستخدم هذا لبعض خيارات CLI غير الحساسة لحالة الأحرف ، على سبيل المثال.
إذا كنت تحب python ولديك خيار لتثبيت حزمة python جديدة ، يمكنك تجربة هذا python utility .
# install pythonp
$ pip install pythonp
$ echo $a | pythonp "l.lower()"
يتم تحويل الحالة للأبجديات فقط. لذلك ، هذا يجب أن تعمل بدقة.
أركز على تحويل الحروف الهجائية بين a-z من الحروف الكبيرة إلى الحروف الصغيرة. يجب أن تطبع أي أحرف أخرى في stdout كما هي ...
يحول النص بالكامل في المسار/إلى/ملف/اسم الملف ضمن نطاق a-z إلى A-Z
لتحويل الحالة الصغيرة إلى الحالة العليا
cat path/to/file/filename | tr 'a-z' 'A-Z'
للتحويل من الأحرف الكبيرة إلى الأحرف الصغيرة
cat path/to/file/filename | tr 'A-Z' 'a-z'
فمثلا،
اسم الملف:
my name is xyz
يتم تحويله إلى:
MY NAME IS XYZ
مثال 2:
echo "my name is 123 karthik" | tr 'a-z' 'A-Z'
# Output:
# MY NAME IS 123 KARTHIK
مثال 3:
echo "my name is 123 &&^&& #@$#@%%& kAR2~thik" | tr 'a-z' 'A-Z'
# Output:
# MY NAME IS 123 &&^&& #@[email protected]%%& KAR2~THIK
لتخزين السلسلة المحولة إلى متغير. عملت التالية بالنسبة لي - $SOURCE_NAME
إلى $TARGET_NAME
TARGET_NAME="`echo $SOURCE_NAME | tr '[:upper:]' '[:lower:]'`"
هذا هو الاختلاف أسرع بكثير من نهج JaredTS486 الذي يستخدم قدرات Bash الأصلية (بما في ذلك إصدارات Bash <4.0) لتحسين مقاربته.
لقد قمت بتوقيت 1000 تكرار لهذا النهج لسلسلة صغيرة (25 حرفًا) وسلسلة أكبر (445 حرفًا) ، لكل من التحويلات الصغيرة والكبيرة. نظرًا لأن سلاسل الاختبار صغيرة في الغالب ، فإن التحويلات إلى الأحرف الصغيرة تكون أسرع بشكل عام من الأحرف الكبيرة.
لقد قارنت نهجي بالعديد من الإجابات الأخرى في هذه الصفحة والمتوافقة مع Bash 3.2. إن مقاربي أكثر فاعلية بكثير من معظم الطرق الموثقة هنا ، وهي أسرع من tr
في عدة حالات.
فيما يلي نتائج توقيت 1000 تكرار من 25 حرفًا:
tr
إلى أحرف صغيرة ؛ 3.81s للأحرف الكبيرةنتائج التوقيت لـ 1000 تكرار من 445 حرفًا (تتكون من قصيدة "The Robin" بواسطة Witter Bynner):
tr
إلى أحرف صغيرة ؛ 4s للأحرف الكبيرةحل:
#!/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}"
}
الطريقة بسيطة: بينما تحتوي سلسلة الإدخال على أي أحرف كبيرة متبقية ، ابحث عن السلسلة التالية ، واستبدل جميع مثيلات تلك الرسالة بصغيرها الصغير. كرر ذلك حتى يتم استبدال جميع الأحرف الكبيرة.
بعض خصائص أداء الحل الخاص بي:
UCS
و LCS
بأحرف إضافية