Linux bash, строка верблюжьего корпуса для разделения тире

Есть ли способ конвертировать что-то вроде этого:

MyDirectoryFileLine

к

my-directory-file-line

Я нашел несколько способов конвертировать все буквы в верхний или нижний регистр, но не таким образом; любые идеи?

Ответы

Ответ 1

Вы можете использовать s/\([AZ]\) / -\L\1/g чтобы найти заглавную букву и заменить ее тире и строчными буквами. Тем не менее, это дает вам черту в начале строки, поэтому вам нужно другое выражение sed, чтобы справиться с этим.

Это должно работать:

sed --expression 's/\([A-Z]\)/-\L\1/g' \
    --expression 's/^-//'              \
    <<< "MyDirectoryFileLine"

Ответ 2

Я предлагаю использовать sed для этого:

NEW=$(echo MyDirectoryFileLine        \
     | sed 's/\(.\)\([A-Z]\)/\1-\2/g' \
     | tr '[:upper:]' '[:lower:]')

UPD забыл перевести в нижний регистр, обновил код

Ответ 3

echo MyDirectoryFileLine | perl -ne 'print lc(join("-", split(/(?=[A-Z])/)))'

печатает my-directory-file-line

Ответ 4

Ни одно из опубликованных здесь решений не сработало для меня. Большинство из них плохо поддерживали несколько платформ. Один из @4ndrew был близок, но он не удался в крайних случаях, когда несколько заглавных букв были рядом друг с другом (пример: FooMVPClient превращается в foo-mv-pclient вместо foo-mvp-client).

Это сработало для меня:

echo "MyDirectoryMVPFileLine"              \
| sed 's/\([a-z]\)\([A-Z]\)/\1-\2/g'       \
| sed 's/\([A-Z]\{2,\}\)\([A-Z]\)/\1-\2/g' \
| tr '[:upper:]' '[:lower:]'

выход:

my-directory-mvp-file-line

Ответ 5

С GNU sed:

echo "MyDirectoryFileLine"|sed -e 's/\([A-Z]\)/-\L\1/g'

Вам просто нужно снять первую тире, если это вас беспокоит:

echo "MyDirectoryFileLine"|sed -e 's/\([A-Z]\)/-\L\1/g' -e 's/^-//'

С BSD sed это немного дольше:

echo "MyDirectoryFileLine"|sed -e 's/\([A-Z]\)/-\1/g' -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/' -e 's/^-//'

Обновление: версия BSD будет работать с версией GNU, поэтому я рекомендую использовать последнюю.

Ответ 6

Это может сработать для вас:

<<<"MyDirectoryFileLine" sed 's/[A-Z]/-\l&/g;s/.//'
my-directory-file-line

Ответ 7

Небольшая вариация ответа @bilalq, которая охватывает еще несколько возможных крайних случаев:

echo "MyDirectoryMVPFileLine"                          \
| sed 's/\([^A-Z]\)\([A-Z0-9]\)/\1-\2/g'               \
| sed 's/\([A-Z0-9]\)\([A-Z0-9]\)\([^A-Z]\)/\1-\2\3/g' \
| tr '[:upper:]' '[:lower:]'

вывод по-прежнему:

my-directory-mvp-file-line

но также:

WhatADeal -> what-a-deal
TheMVP -> the-mvp
DoSomeABTesting -> do-some-ab-testing
The3rdThing -> the-3rd-thing
The3Things -> the-3-things
ThingNumber3 -> thing-number-3