Как я могу сократить (1) верблюжьих слов?
-
03-07-2019 - |
Вопрос
Есть ли в Bash простой способ разбить слово на верблюде на составляющие его слова?
Например, я хочу разделить aCertainCamelCasedWord на «Определенное слово в верблюжьих словах» и иметь возможность выбирать те поля, которые меня интересуют. Это тривиально делается с помощью cut (1), когда разделитель слов является подчеркиванием, но как я могу это сделать, когда слово занято верблюдом?
Решение
sed 's / \ ([A-Z] \) / \ 1 / g'
Захватывает каждую заглавную букву и заменяет начальный пробел на весь поток.
$ echo "aCertainCamelCasedWord" | sed 's/\([A-Z]\)/ \1/g'
a Certain Camel Cased Word
Другие советы
Это решение работает, если вам не нужно разбивать слова на заглавные. Например, используя верхний ответ, вы получите:
$ echo 'FAQPage' | sed 's/\([A-Z]\)/ \1/g'
F A Q Page
Но вместо этого с моим решением вы получите:
$ echo 'FAQPage' | sed 's/\([A-Z][^A-Z]\)/ \1/g'
FAQ Page
Примечание. Это работает некорректно, когда существует второй экземпляр нескольких заглавных слов, например:
$ echo 'FAQPageOneReplacedByFAQPageTwo' | sed 's|\([A-Z][^A-Z]\)| \1|g'
FAQ Page One Replaced ByFAQ Page Two
Этот ответ не работает правильно, если есть второй экземпляр нескольких заглавных букв
echo 'FAQPageOneReplacedByFAQPageTwo' | sed 's|\([A-Z][^A-Z]\)| \1|g'
FAQ Page One Replaced ByFAQ Page Two
Итак, для этого требуется дополнительное выражение
echo 'FAQPageOneReplacedByFAQPageTwo' | sed -e 's|\([A-Z][^A-Z]\)| \1|g' -e 's|\([a-z]\)\([A-Z]\)|\1 \2|g'
FAQ Page One Replaced By FAQ Page Two
Pure Bash:
name="aCertainCamelCasedWord"
declare -a word # the word array
counter1=0 # count characters
counter2=0 # count words
while [ $counter1 -lt ${#name} ] ; do
nextchar=${name:${counter1}:1}
if [[ $nextchar =~ [[:upper:]] ]] ; then
((counter2++))
word[${counter2}]=$nextchar
else
word[${counter2}]=${word[${counter2}]}$nextchar
fi
((counter1++))
done
echo -e "'${word[@]}'"