将蛇形大小写转换为驼峰大小写,直到使用 sed 的特殊字符

convert snake case to camel case until a special character with sed

我正在尝试将 Localizable.strings 的密钥从 Mac 上的蛇形外壳转换为驼峰外壳。我可以使用 gsed,因为它支持 \U 大写。

我的文件如下所示:

/* Title  */
"home.title" = "Welcome";

/* Email  */
"home.signup_email" = "Email";

/* recover_email  */
"home.signup_email_recover" = "Recover Email";

/* password  */
"home.password" = "Enter your __Password__:";

我希望修改此文件以获得此:

/* Title  */
"home.title" = "Welcome";

/* Email  */
"home.signupEmail" = "Email";

/* recover_email  */
"home.signupEmailRecover" = "Recover Email";

/* password  */
"home.password" = "Enter your __Password__:";

我尝试将 gsed 与类似的东西一起使用,但不幸的是,我无法在 = 字符之后停止。

find . -name "*.strings" | xargs gsed -i -e '/=/! s/_\([a-z]\)/\U/gi'

知道如何在 = 之后停止替换 _ 吗?

谢谢!

您可以使用

sed ':a;s/^\([^=]*\)_\([[:alpha:]]\)/\U\E/;ta'

如果您只想替换 _ + 小写字母,您也可以使用 [[:lower:]] 而不是 [[:alpha:]]

详情:

  • :a - 设置一个 a 标签
  • s/^\([^=]*\)_\([[:alpha:]]\)/\U\E/ - 找到除 = 字符以外的任何零个或多个字符并将其捕获到第 1 组中,然后匹配 _ 然后将任何字母捕获到组中,然后替换第 1 组 + 第 1 组中的大写字母
  • ta - 如果替换成功,则跳回到 a 标签位置。

参见 online demo:

#!/bin/bash
s='/* Title  */
"home.title" = "Welcome";
 
/* Email  */
"home.signup_email" = "Email";
 
/* recover_email  */
"home.signup_email_recover" = "Recover Email";
 
/* password  */
"home.password" = "Enter your __Password__:";

/* One more string */
"my_string_key" = "[Click here](https://my.url.com/deeplink?id=UUID&section_id=foo)";'
sed ':a;s/^\([^=]*\)_\([[:alpha:]]\)/\U\E/;ta' <<< "$s"

输出:

/* Title  */
"home.title" = "Welcome";
 
/* Email  */
"home.signupEmail" = "Email";
 
/* recoverEmail  */
"home.signupEmailRecover" = "Recover Email";
 
/* password  */
"home.password" = "Enter your __Password__:";

/* One more string */
"myStringKey" = "[Click here](https://my.url.com/deeplink?id=UUID&section_id=foo)";

有点冗长,但这里有一个 non-regex 方法,使用 OSX 上可用的默认 BSD awk:

awk '
BEGIN {FS=OFS="="}
NF == 2 && (n = split(, a, /_/)) {
   s = a[1]
   for (i=2; i<=n; ++i)
      s = s toupper(substr(a[i], 1, 1)) substr(a[i], 2)
    = s
} 1' file

/* Title  */
"home.title" = "Welcome";

/* Email  */
"home.signupEmail" = "Email";

/* recover_email  */
"home.signupEmailRecover" = "Recover Email";

/* password  */
"home.password" = "Enter your __Password__:";

如果您不介意 gnu gawk 特定的解决方案:

           # always true condition whether
           # ORS contains empty string
           #
  gawk    '(ORS=toupper(substr(RT,2)))~_'     RS='_[a-z]' file
or
           #     +ORS is always 0/false,
           # so !+ORS is always 1/ true
           #
  gawk  '!+(ORS=toupper(substr(RT,2)))'       RS='_[a-z]' file
or
  gawk 'sub(/$/,toupper(substr(RT,2)))' ORS=  RS='_[a-z]' file
or
           # this just means 
           # 0-to-0th-power
           #
  gawk 'FS^(ORS=toupper(substr(RT,2)))'       RS='_[a-z]' file  
or
           # ASCII string-compare that is always true since
           # underscore "_" has higher byte ordinance than
           # either empty string or any ASCII uppercase letters
           #
  gawk '(ORS=toupper(substr(RT,2)))<RS'       RS='_[a-z]' file

=

/* Title  */
"home.title" = "Welcome";

/* Email  */
"home.signupEmail" = "Email";

/* recoverEmail  */
"home.signupEmailRecover" = "Recover Email";

/* password  */
"home.password" = "Enter your __Password__:";