我有一个 sed 脚本,可以将 camelCase 转换为 under_score,这对于此示例非常有用:
myvar="camelCase"
converted="$(echo $myvar | sed 's/\([A-Z]\)/_\L\1/g;s/^_//')"
echo converted
// result: camel_case
但是,我遇到过以下这种情况:
myvar="camelCASE"
converted="$(echo $myvar | sed 's/\([A-Z]\)/_\L\1/g;s/^_//')"
echo converted
// result: camel_c_a_s_e
在这种特殊情况下我需要的结果是:camel_case。
需要明确的是,最终的 sed 脚本应该适用于“camelCase”以及“camelCASE”和“CAMELcase”。
myvar 不得包含特殊字符或空格
答案1
你必须考虑到大小写变化是单词的标记。_
在大小写变化之前必须放置空格
尝试这个 :
$ echo 'CamelCASECamelCase' \
| 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:]'
# will output this
camel_case_camel_case
答案2
问题是您\([A-Z]\)
一次只能捕获一个大写字母。要在 POSIX BRE sed 中修复此问题,您可以使用\([A-Z]\{1,\}\)
ex。
$ echo camelCASE | sed 's/\([A-Z]\{1,\}\)/_\L\1/g;s/^_//'
camel_case
至少在 GNU sed 中,你可以_
通过仅在非分词后进行匹配来避免前导的特殊处理
$ echo CamelCASE | sed 's/\B\([A-Z]\{1,\}\)/_\L\1/g'
Camel_case
在 ERE 中可读性更强
$ echo CamelCASECamelCase | sed -E 's/\B([A-Z]+)/_\L\1/g'
Camel_casecamel_case
甚至(使用&
而不是显式分组)
$ echo CamelCASECamelCase | sed -E 's/\B[A-Z]+/_\L&/g'
Camel_casecamel_case