linux bash,驼峰式字符串用破折号分隔
Posted
技术标签:
【中文标题】linux bash,驼峰式字符串用破折号分隔【英文标题】:linux bash, camel case string to separate by dash 【发布时间】:2012-01-20 03:19:51 【问题描述】:有没有办法像这样转换:
MyDirectoryFileLine
到
my-directory-file-line
我找到了一些将所有字母转换为大写或小写的方法,但不是那种方式;有什么想法吗?
【问题讨论】:
从脊椎病例到骆驼病例,可以参考:***.com/questions/34420091/… 【参考方案1】:您可以使用s/\([A-Z]\)/-\L\1/g
查找大写字母并将其替换为破折号并且它是小写字母。但是,这会在行的开头给您一个破折号,因此您需要另一个 sed 表达式来处理它。
这应该可行:
sed --expression 's/\([A-Z]\)/-\L\1/g' \
--expression 's/^-//' \
<<< "MyDirectoryFileLine"
【讨论】:
我用过类似的东西:tmp2=echo $tmp[@], | sed -e 's/\([A-Z]\)/-\L\1/g'
无法在 OS X 上开箱即用 - 请参阅 @4ndrew 的版本以了解也适用于 OS X 的解决方案。
对于 OS X 使用:sed -e 's/\([A-Z]\)/-\1/g' -e 's/^-//' <<< "MyDirectoryFileLine"
- 基本上从 sed 替换中删除 \L
留下领先的-
,例如-my-var-name
。执行额外的 sed pass 以删除。【参考方案2】:
我建议使用 sed 来做到这一点:
NEW=$(echo MyDirectoryFileLine \
| sed 's/\(.\)\([A-Z]\)/\1-\2/g' \
| tr '[:upper:]' '[:lower:]')
UPD我忘记转换为小写,更新代码
【讨论】:
您“建议使用 awk”,但在您的答案中使用 sed? 这太棒了,因为它也适用于 OS X sed,无需安装 gnu 版本。【参考方案3】:echo MyDirectoryFileLine | perl -ne 'print lc(join("-", split(/(?=[A-Z])/)))'
打印my-directory-file-line
【讨论】:
很好,但是 perl 是不是有点矫枉过正? 现在调用 Perl 并没有真正使用 Bash,是吗?【参考方案4】:@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
【讨论】:
【参考方案5】:此处发布的解决方案均不适合我。大多数都不能很好地支持多个平台。来自@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
【讨论】:
【参考方案6】:我的微薄贡献与“/”一起使用(可能用于目录名称或 github 存储库名称)。它不像它可能的那样干净,但可以完成工作。我以@Peter 的贡献为基础,然后进行了一些调整。
function kebab_case()
echo -n "$1" |\
sed 's/\([^A-Z+]\)\([A-Z0-9]\)/\1-\2/g' |\
sed 's/\([0-9]\)\([A-Z]\)/\1-\2/g' |\
sed 's/\([A-Z]\)\([0-9]\)/\1-\2/g' |\
sed 's/--/-/g' |\
sed 's/\([\/]\)-/\1/g' |\
tr '[:upper:]' '[:lower:]'
function assert_kebab_equal()
local Actual
local Expected
Expected="$1"
Actual="$(kebab_case "$2")"
if [ "$Expected" != "$Actual" ]; then
echo Error:
echo " Actual: $Actual"
echo "Expected: $Expected"
else
echo "$2" "$1" | awk ' printf "%-30s -> %-40s\n", $1, $2'
fi
assert_kebab_equal "abc-def" "AbcDef"
assert_kebab_equal "/abc-def-ghi/def" "/AbcDef-Ghi/Def"
assert_kebab_equal "/ab-cd-ef" "/AbCdEf"
assert_kebab_equal "repo-owner/repo-name" "RepoOwner/RepoName"
assert_kebab_equal "repo-12-owner/repo-12-name" "Repo12Owner/Repo12Name"
assert_kebab_equal "repo-12-3-owner/repo-12-name" "Repo12-3Owner/Repo12Name"
assert_kebab_equal "repo-owner/repo-name" "REPO-OWNER/REPO-NAME"
assert_kebab_equal "repo-owner-2/repo-name" "REPO-OWNER2/REPO-NAME"
assert_kebab_equal "repo-1-owner" "REPO1-OWNER"
assert_kebab_equal "repo-1-owner-1/22-repo-2-name" "REPO1-OWNER1/22REPO-2NAME"
# Outputs:
AbcDef -> abc-def
/AbcDef-Ghi/Def -> /abc-def-ghi/def
/AbCdEf -> /ab-cd-ef
RepoOwner/RepoName -> repo-owner/repo-name
Repo12Owner/Repo12Name -> repo-12-owner/repo-12-name
Repo12-3Owner/Repo12Name -> repo-12-3-owner/repo-12-name
REPO-OWNER/REPO-NAME -> repo-owner/repo-name
REPO-OWNER2/REPO-NAME -> repo-owner-2/repo-name
REPO1-OWNER -> repo-1-owner
REPO1-OWNER1/22REPO-2NAME -> repo-1-owner-1/22-repo-2-name
【讨论】:
【参考方案7】:这可能对你有用:
<<<"MyDirectoryFileLine" sed 's/[A-Z]/-\l&/g;s/.//'
my-directory-file-line
【讨论】:
【参考方案8】:使用 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 版本兼容,所以我推荐使用后者。
【讨论】:
【参考方案9】:echo "SomeACRONYMInCamelCaseString" \
| sed -e 's/\([a-z]\)\([A-Z]\)/\1-\L\2/' \
| sed -e 's/\(.*\)/\L\1/')
sed -e 's/\([a-z]\)\([A-Z]\)/\1-\L\2/'
用连字符和小写字母替换大写字母,前提是它前面有一个小写字母。
sed -e 's/\(.*\)/\L\1/'
将整个字符串小写
【讨论】:
以上是关于linux bash,驼峰式字符串用破折号分隔的主要内容,如果未能解决你的问题,请参考以下文章