Как преобразовать строку в нижний регистр в Bash?
Есть ли способ в bash преобразовать строку в строчную строку?
Например, если у меня есть:
a="Hi all"
Я хочу преобразовать его в:
- Проверка наличия строкового массива, и если да, то его позиция
- Что означает значение $ перед строкой?
- Какова цель выражения «new String (...)» в Java?
- Измените строку с помощью указателя
- Как преобразовать строку в enum в C #?
"hi all"
- Нечувствительность к регистру std :: string.find ()
- Как преобразовать целое число цвета в шестнадцатеричную строку в Android?
- Простой способ удалить несколько пробелов в строке?
- Как работает strcmp ()?
- Строковый вывод: формат или concat в C #?
- Нечувствительный к регистру «Содержит (строка)»
- Как превратить формулу строки в «реальную» формулу
- Что такое начальное значение Java String по умолчанию?
Существуют различные способы:
тр
$ echo "$a" | tr '[:upper:]' '[:lower:]' hi all
AWK
$ echo "$a" | awk '{print tolower($0)}' hi all
Bash 4.0
$ echo "${a,,}" hi all
СЕПГ
$ echo "$a" | sed -e 's/\(.*\)/\L\1/' hi all # this also works: $ sed -e 's/\(.*\)/\L\1/' <<< "$a" hi all
Perl
$ echo "$a" | perl -ne 'print lc' hi all
удар
lc(){ case "$1" in [AZ]) 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
В Bash 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
Toggle (недокументированный, но необязательно настраиваемый во время компиляции)
$ 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
изменяют атрибут переменной, но не содержимое. Перераспределения в моих примерах обновляют содержимое, чтобы показать изменения.
Редактировать:
Добавлен «переключить первый символ по слову» ( ${var~}
), как было предложено ghostdog74 .
Изменить: Исправлено поведение тильды в соответствии с Bash 4.3.
echo "Hi All" | tr "[:upper:]" "[:lower:]"
tr :
a="$(tr [AZ] [az] <<< "$a")"
AWK :
{ print tolower($0) }
sed :
y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
Я знаю, что это старая должность, но я сделал этот ответ для другого сайта, поэтому я подумал, что я опубликую его здесь:
UPPER -> lower : используйте python:
b=`echo "print '$a'.lower()" | python`
Или Рубин:
b=`echo "print '$a'.downcase" | ruby`
Или Perl (возможно, мой любимый):
b=`perl -e "print lc('$a');"`
Или PHP:
b=`php -r "print strtolower('$a');"`
Или Awk:
b=`echo "$a" | awk '{ print tolower($1) }'`
Или Sed:
b=`echo "$a" | sed 's/./\L&/g'`
Или Bash 4:
b=${a,,}
Или NodeJS, если у вас есть (и немного орехи …):
b=`echo "console.log('$a'.toLowerCase());" | node`
Вы также можете использовать dd
(но я бы не стал!):
b=`echo "$a" | dd conv=lcase 2> /dev/null`
ниже -> ВЕРХ :
использовать python:
b=`echo "print '$a'.upper()" | python`
Или Рубин:
b=`echo "print '$a'.upcase" | ruby`
Или Perl (возможно, мой любимый):
b=`perl -e "print uc('$a');"`
Или PHP:
b=`php -r "print strtoupper('$a');"`
Или Awk:
b=`echo "$a" | awk '{ print toupper($1) }'`
Или Sed:
b=`echo "$a" | sed 's/./\U&/g'`
Или Bash 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
Для стандартной оболочки (без багизмов), использующей только встроенные функции:
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}" }
Pre Bash 4.0
Bash Опустить случай строки и присвоить переменной
VARIABLE=$(echo "$VARIABLE" | tr '[:upper:]' '[:lower:]') echo "$VARIABLE"
Регулярное выражение
Я хотел бы взять кредит за команду, которую хочу поделиться, но, по правде говоря, я получил ее для собственного использования с http://commandlinefu.com . Преимущество заключается в том, что если вы cd
к любому каталогу в своей домашней папке, то это приведет к изменению всех файлов и папок на более низкий регистр рекурсивно, пожалуйста, используйте с осторожностью. Это блестящее исправление командной строки и особенно полезно для тех множества альбомов, которые вы сохранили на своем диске.
find . -depth -exec rename 's/(.*)\/([^\/]*)/$1\/\L$2/' {} \;
Вы можете указать каталог вместо точки (.) После поиска, которая обозначает текущий каталог или полный путь.
Надеюсь, это решение окажется полезным тем, что эта команда не делает, это заменить пробелы символами подчеркивания – возможно, еще раз.
В bash 4 вы можете использовать набор
Пример:
A="HELLO WORLD" typeset -l A=$A
Вы можете попробовать это
s="Hello World!" echo $s # Hello World! a=${s,,} echo $a # hello world! b=${s^^} echo $b # HELLO WORLD!
ref: http://wiki.workassis.com/shell-script-convert-text-to-lowercase-and-uppercase/
При использовании 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" )
- В lcase-функции, используя
${!1//\'/"'\''"}
вместо${!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 [AZ] ) printf -v __decimal '%d' "'$__char" printf -v __octal '%03o' $(( $__decimal ^ 0x20 )) printf -v __char \\$__octal ;; esac __result+="$__char" done REPLY="$__result" }
Ответ на технозавр тоже имел потенциал, хотя он действительно работал правильно.
Несмотря на то, насколько старый этот вопрос и похож на этот ответ технозавром . Мне было трудно найти решение, которое было переносимым на большинстве платформ (That I Use), а также более старые версии bash. Я также был расстроен массивами, функциями и использованием отпечатков, эхо и временных файлов для извлечения тривиальных переменных. Это очень хорошо для меня, я думал, что поделюсь. Моей основной средой тестирования являются:
- GNU bash, версия 4.1.2 (1) -release (x86_64-redhat-linux-gnu)
- GNU bash, версия 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
Простой C-стиль для цикла для итерации по строкам. Для строки ниже, если вы не видели ничего подобного, прежде чем я узнаю об этом . В этом случае строка проверяет, существует ли символ char $ {input: $ i: 1} (нижний регистр), и если он заменяет его заданным char $ {ucs: $ j: 1} (верхний регистр) и сохраняет его обратно на вход.
input="${input/${input:$i:1}/${ucs:$j:1}}"
Многие ответы используют внешние программы, которые на самом деле не используют Bash
.
Если вы знаете, что у вас будет ansible Bash4, вы должны просто использовать нотацию ${VAR,,}
(это легко и круто). Для Bash до 4 (например, у меня Mac по-прежнему используется Bash 3.2). Я использовал исправленную версию ответа @ ghostdog74 для создания более переносимой версии.
Один из них можно вызвать в lowercase 'my STRING'
и получить версию в нижнем регистре. Я читал комментарии о настройке результата на var, но это не очень портативно в Bash
, так как мы не можем вернуть строки. Печать – лучшее решение. Легко захватывать с чем-то вроде var="$(lowercase $str)"
.
Как это работает
Способ, которым это работает, заключается в получении целочисленного представления ASCII каждого символа с printf
а затем adding 32
если upper-to->lower
, или subtracting 32
если lower-to->upper
. Затем снова используйте printf
чтобы преобразовать число обратно в символ. Из '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 [AZ]) 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 [az]) 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
И результаты после этого:
$ ./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.
Преобразование дела выполняется только для алфавитов. Таким образом, это должно работать аккуратно.
Я сосредоточен на преобразовании алфавитов между az от верхнего регистра к нижнему регистру. Любые другие символы должны быть напечатаны только в стандартном режиме, так как это …
Преобразует весь текст в путь / в / file / filename в диапазоне az до AZ
Для преобразования нижнего регистра в верхний регистр
cat path/to/file/filename | tr 'az' 'AZ'
Для преобразования от верхнего регистра к нижнему регистру
cat path/to/file/filename | tr 'AZ' 'az'
Например,
имя файла:
my name is xyz
преобразуется в:
MY NAME IS XYZ
Пример 2:
echo "my name is 123 karthik" | tr 'az' 'AZ' # Output: # MY NAME IS 123 KARTHIK
Пример 3:
echo "my name is 123 &&^&& #@$#@%%& kAR2~thik" | tr 'az' 'AZ' # Output: # MY NAME IS 123 &&^&& #@0@%%& 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 символов:
- 0.46s для моего подхода к нижнему регистру; 0.96s для верхнего регистра
- 1.16s для подхода Овервелофила к нижнему регистру ; 1.59s для верхнего регистра
- 3.67s для
tr
в нижний регистр; 3.81s для верхнего регистра - 11.12s для подхода ghostdog74 к нижнему регистру ; 31.41s для верхнего регистра
- 26.25s для подхода технозавров к нижнему регистру ; 26.21s для верхнего регистра
- 25.06s для подхода JaredTS486 к нижнему регистру ; 27.04s для верхнего регистра
Сроки для 1000 итераций 445 символов (состоящие из стихотворения «Робин» Уитнера Биннера):
- 2s для моего подхода к нижнему регистру; 12s для верхнего регистра
- 4s для
tr
в нижний регистр; 4s для верхнего регистра - 20-е годы для подхода Овервелофила к нижнему регистру ; 29s для верхнего регистра
- 75s для подхода ghostdog74 к нижнему регистру ; 669s для верхнего регистра. Интересно отметить, насколько сильно разница в производительности между тестом с преобладающими совпадениями против теста с преобладающими промахами
- 467s для подхода технозавров к нижнему регистру ; 449s для верхнего регистра
- 660s для подхода JaredTS486 к нижнему регистру ; 660s для верхнего регистра. Интересно отметить, что этот подход вызвал непрерывные ошибки страниц (свопинг памяти) в Bash
Решение:
#!/bin/bash set -e set -u declare LCS="abcdefghijklmnopqrstuvwxyz" declare UCS="ABCDEFGHIJKLMNOPQRSTUVWXYZ" function lcase() { local TARGET="${1-}" local UCHAR='' local UOFFSET='' while [[ "${TARGET}" =~ ([AZ]) ]] 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}" =~ ([az]) ]] do LCHAR="${BASH_REMATCH[1]}" LOFFSET="${LCS%%${LCHAR}*}" TARGET="${TARGET//${LCHAR}/${UCS:${#LOFFSET}:1}}" done echo -n "${TARGET}" }
Подход прост: в то время как строка ввода содержит любые оставшиеся заглавные буквы, найдите следующую и замените все экземпляры этой буквы своим нижним регистром. Повторяйте, пока не будут заменены все заглавные буквы.
Некоторые характеристики производительности моего решения:
- Использует только встроенные утилиты shell, которые позволяют избежать накладных расходов при вызове внешних двоичных утилит в новом процессе
- Избегает подclassов, которые несут штрафы за производительность
- Использует механизмы оболочки, которые скомпилированы и оптимизированы для производительности, такие как глобальная замена строки внутри переменных, обрезка суффикса переменных и поиск и сопоставление регулярных выражений. Эти механизмы намного быстрее, чем итерация вручную через строки
- Циклирует только количество раз, необходимое для подсчета уникальных совпадающих символов для преобразования. Например, преобразование строки с тремя разными прописными буквами в нижний регистр требует только трех итераций цикла. Для предварительно сконфигурированного алфавита ASCII максимальное число итераций цикла составляет 26
-
UCS
иLCS
могут быть дополнены дополнительными символами