Как преобразовать строку в нижний регистр в Bash?



есть ли способ в Баш чтобы преобразовать строку в строку нижнего регистра?



например, если у меня есть:



a="Hi all"


Я хочу преобразовать его в:



"hi all"
1124   19  

19 ответов:

существуют различные способы:

POSIX standard

tr

$ echo "$a" | tr '[:upper:]' '[:lower:]'
hi all

AWK

$ echo "$a" | awk '{print tolower()}'
hi all

Non-POSIX

вы можете столкнуться с проблемами переносимости следующие примеры:

Баш 4.0

$ echo "${a,,}"
hi all

sed

$ echo "$a" | sed -e 's/\(.*\)/\L/'
hi all
# this also works:
$ sed -e 's/\(.*\)/\L/' <<< "$a"
hi all

Perl

$ echo "$a" | perl -ne 'print lc'
hi all

Баш

lc(){
    case "" in
        [A-Z])
        n=$(printf "%d" "'")
        n=$((n+32))
        printf \$(printf "%o" "$n")
        ;;
        *)
        printf "%s" ""
        ;;
    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

Capitalize (недокументированный, но при необходимости настраивается во время компиляции)

$ string="a few words"
$ declare -c string
$ string=$string
$ echo "$string"
A few words

Title case:

$ 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

чтобы отключить a

echo "Hi All" | tr "[:upper:]" "[:lower:]"

tr:

a="$(tr [A-Z] [a-z] <<< "$a")"

AWK:

{ print tolower() }

sed:

y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/

я знаю, что это старый пост, но я сделал этот ответ для другого сайта, поэтому я думал, что опубликую его здесь:

верхний -> нижний: используйте python:

b=`echo "print '$a'.lower()" | python`

Или Ruby:

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() }'`

Или 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`

Или Ruby:

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() }'`

Или 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

Я люблю ЗШ!

С помощью 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/(.*)\/([^\/]*)/\/\L/' {} \;

вы можете указать каталог вместо точки(.) после поиска, который обозначает текущий каталог или полный путь.

Я надеюсь, что это решение окажется полезным одна вещь, которую эта команда не делает, это заменить пробелы подчеркиванием - ну, в другой раз, возможно.

в bash 4 Вы можете использовать typeset

пример:

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!

enter image description here

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 ""=\'$(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=
   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"
}

ответ технозавра был потенциал тоже, хотя он работал должным образом для Ми.

несмотря на то, насколько стар этот вопрос и похож на это ответ технозавра. Мне было трудно найти решение, которое было переносимым на большинстве платформ (которые я использую), а также более старые версии bash. Я также был разочарован массивами, функциями и использованием отпечатков, эхо-сигналов и временных файлов для извлечения тривиальных переменных. Это работает очень хорошо для меня до сих пор я думал, что поделюсь. Мои основные среды тестирования:

  1. GNU bash, версия 4.1.2 (1)-release (x86_64-redhat-linux-gnu)
  2. 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-стиль для петли для перебора строк. На строку ниже, если вы не видели ничего подобного раньше вот где я этому научился. В этом случае строка проверяет, существует ли символ ${input:$i:1} (нижний регистр) во input и если да, то заменяет его заданным символом ${ucs:$j: 1} (верхний регистр) и сохраняет его обратно во вход.

input="${input/${input:$i:1}/${ucs:$j:1}}"

многие ответы с использованием внешних программ, которые на самом деле не используют Bash.

если вы знаете, что у вас будет 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 снова преобразовывать число обратно в 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 "" in
        [A-Z])
            n=$(printf "%d" "'")
            n=$((n+32))
            printf \$(printf "%o" "$n")
            ;;
        *)
            printf "%s" ""
            ;;
    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 "" in
        [a-z])
            n=$(printf "%d" "'")
            n=$((n-32))
            printf \$(printf "%o" "$n")
            ;;
        *)
            printf "%s" ""
            ;;
    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 без учета регистра, например.

преобразование дело делается только для алфавитов. Так что, это должно работать аккуратно.

Я сосредоточен на преобразовании алфавитов между a-z из верхнего регистра в нижний регистр. Любые другие символы должны быть напечатаны в stdout, как это...

преобразует весь текст в path / to/file / filename в диапазоне 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 &&^&& #@0@%%& KAR2~THIK

для хранения преобразованной строки в переменную. Следующие работал для меня - $SOURCE_NAME to $TARGET_NAME

TARGET_NAME="`echo $SOURCE_NAME | tr '[:upper:]' '[:lower:]'`"

это гораздо более быстрый вариант подход JaredTS486 который использует собственные возможности Bash (включая версии Bash

Я рассчитал 1000 итераций этого подхода для небольшой строки (25 символов) и большей строки (445 символов), как для строчных, так и для прописных преобразований. Поскольку тестовые строки преимущественно строчные, преобразования в строчные обычно выполняются быстрее, чем в прописные.

Я сравнил мой подход с несколькими другими ответами на этой странице, которые совместимы с Bash 3.2. Мой подход гораздо более эффективен, чем большинство подходов, описанных здесь, и даже быстрее, чем tr в нескольких случаях.

вот результаты синхронизации для 1000 итераций 25 символов:

  • 0.46 s для моего подхода к строчному регистру; 0.96 s для верхнего регистра
  • 1.16 s для Orwellophile это в нижнем регистре; 1.59 s для прописные буквы
  • 3,67 С для tr в нижнем регистре; 3.81 s для верхнего регистра
  • 11.12 s для подход ghostdog74 в нижнем регистре; 31.41 s для верхнего регистра
  • 26.25 s для подход технозавра в нижнем регистре; 26.21 s для верхнего регистра
  • 25.06 s для подход JaredTS486 в нижнем регистре; 27.04 s для верхнего регистра

результаты синхронизации для 1000 итераций 445 символов (состоящий из стихотворения "Малиновка" Уиттера Биннера):

  • 2s для моего подхода в нижнем регистре; 12s для верхнего регистра
  • 4s для tr в нижнем регистре; 4s для верхнего регистра
  • 20s для Orwellophile это в нижнем регистре; 29s для верхнего регистра
  • 75s для ghostdog74 это подход к строчному регистру; 669 для верхнего регистра. Интересно отметить, насколько драматична разница в производительности между тестом с преобладающими совпадениями и тестом с преобладающие промахи
  • 467s для подход технозавра в нижнем регистре; 449s для верхнего регистра
  • 660-е годы для подход JaredTS486 в нижнем регистре; 660 для верхнего регистра. Интересно отметить, что этот подход генерировал непрерывные ошибки страницы (замена памяти) в Bash

устранение:

#!/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}"
}

подход прост: в то время как входная строка содержит все оставшиеся прописные буквы, найдите следующую, и замените все экземпляры этой буквы ее строчным вариантом. Повторяйте до тех пор, пока все заглавные буквы не будут заменены.

некоторые характеристики моего решения:

  1. использует только встроенные утилиты оболочки, что позволяет избежать накладных расходов на вызов внешних двоичных утилит в новом процессе
  2. избегает суб-оболочек, которые несут штрафы за производительность
  3. использует механизмы оболочки, которые скомпилированы и оптимизированы для повышения производительности, такие как глобальная замена строк в переменных, обрезка суффиксов переменных и поиск и сопоставление регулярных выражений. Эти механизмы намного быстрее, чем итерация вручную через строки
  4. циклы только количество раз, необходимое для количества уникальных совпадающих символов, которые будут преобразованы. Например, для преобразования строки, содержащей три разных символа верхнего регистра в Нижний, требуется всего 3 итерации цикла. Для предварительно настроенного алфавита ASCII максимальное число итераций цикла это 26
  5. UCS и LCS можно дополнить дополнительными символами

Comments

    Ничего не найдено.