Как преобразовать строку в нижний регистр в Bash? - PullRequest
1083 голосов
/ 15 февраля 2010

Есть ли в способ преобразовать строку в строчную?

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

a="Hi all"

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

"hi all"

Ответы [ 20 ]

7 голосов
/ 23 марта 2017

Вы можете попробовать это

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/

7 голосов
/ 24 января 2011

Регулярное выражение

Я хотел бы взять кредит на команду, которой хочу поделиться, но правда в том, что я получил ее для собственного использования от http://commandlinefu.com. Преимущество этого в том, что если вы cd перейдете в любой каталог в пределах своей Домашняя папка, то есть рекурсивно изменяет все файлы и папки на строчные, пожалуйста, используйте с осторожностью. Это великолепное исправление командной строки, особенно полезное для множества альбомов, которые вы сохранили на своем диске.

find . -depth -exec rename 's/(.*)\/([^\/]*)/$1\/\L$2/' {} \;

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

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

3 голосов
/ 16 мая 2017

Многие ответы используют внешние программы, которые на самом деле не используют 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, чтобы преобразовать число обратно в символ. От '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="$@"
    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

И результаты после запуска этого:

$ ./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 без учета регистра, например.

3 голосов
/ 23 декабря 2015

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

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

input="${input/${input:$i:1}/${ucs:$j:1}}"
3 голосов
/ 23 марта 2013

При использовании 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} позволяет работать, даже если строка содержит кавычки.
3 голосов
/ 24 марта 2013

Для версий 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"
}

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

2 голосов
/ 03 января 2019

Если вам нравится python и у вас есть возможность установить новый пакет python, вы можете попробовать эту утилиту python .

# install pythonp
$ pip install pythonp

$ echo $a | pythonp "l.lower()"
2 голосов
/ 06 марта 2018

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

Я концентрируюсь на преобразовании алфавитов между 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 &&^&& #@0@%%& KAR2~THIK
1 голос
/ 28 июля 2018

Это гораздо более быстрый вариант подхода JaredTS486 , который использует собственные возможности Bash (включая версии Bash <4.0) для оптимизации его подхода. </p>

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

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

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

  • 0,46 с для моего подхода к нижнему регистру; 0,96 с для прописных букв
  • 1,16 с для Подход Орвеллофила к нижнему регистру; 1,59 с для прописных букв
  • 3,67 для строчных букв tr; 3,81 для прописных букв
  • 11,12 с для подхода ghostdog74 в нижнем регистре; 31,41с для прописных букв
  • 26,25 с для подхода технозавра к нижнему регистру; 26,21с заглавными буквами
  • 25,06 для подход JaredTS486 к нижнему регистру; 27.04 с для прописных букв

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

  • 2 для моего подхода к строчным буквам; 12с прописными буквами
  • 4s для tr в нижнем регистре; 4с прописными буквами
  • 20 с для Подход Орвеллофила к нижнему регистру; 29с прописными буквами
  • 75 с для ghostdog74's подход к нижнему регистру; 669 для прописных. Интересно отметить, насколько значительна разница в производительности между тестом с преобладающими совпадениями и тестом с преобладающими промахами
  • 467 с для подхода технозавра к нижнему регистру; 449 для прописных букв
  • 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 могут быть дополнены дополнительными символами
0 голосов
/ 08 июля 2016

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

TARGET_NAME="`echo $SOURCE_NAME | tr '[:upper:]' '[:lower:]'`"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...