使用 sed 将 camelCase 转换为 under_score

使用 sed 将 camelCase 转换为 under_score

我有一个 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

相关内容