得到一个带有此命令的 makefile,该命令将文件夹名称./cmd/
从snake_case
转换为PascalCase
test:
@for f in $(shell ls ./cmd/); do \
echo $${f}; \
echo $${f} | sed -r 's/(^|_)([a-z])/\U\2/g'; \
done
当我运行它时,我得到的是带有前缀大写字母的U
:
api_get_manual
UapiUgetUmanual
我期望得到什么:
ApiGetManual
\U
,像-r
(-E
现在是标准等价物)是 的 GNU 实现的非标准扩展sed
,受到ex
/ 的启发vi
,也在 中找到perl
,在许多其他实现中找不到。在这里,你可以这样做:
使用:
cmd/*(N:t)
以 ullglob 方式扩展 globN
,获得t
每次扩展的结果。${(C)var}
将变量中的单词大写${var//_}
按照 ksh 的方式删除_
之后的字符print -rl --
在单独的线上打印r
awl
。请注意,文件名将根据用户的区域设置(LC_CTYPE 类别)解码为文本并转换为大写。
对于每个包含一个或多个字母数字字符的序列,上述操作将第一个字符转换为大写,将其余所有字符转换为小写,并删除所有下划线。
与您的方法更接近的匹配是仅删除后跟小写字母的下划线(并且仅将该字母转换为大写,其余字母保持不变):
在哪里
(#b)
是为了激活反向引用,因此可以$match
在替换中的数组中引用捕获组(#s)
对于s
tart,相当于正则表达式^
[[:lower:]]
匹配正则表达式中分类为小写的字符。[a-z]
限制为a
和之间的z
字符,zsh
基于代码点值,因此限制为 abcdefghijklmnopqrstuvwxyz$var:u
像在 csh 中一样转换为大写,尊重语言环境。没有
zsh
:假设 ASCII 仅有字母(例如,
stéphane
将被更改为不被识别为字母)。StéPhane
é
或者像你的方法一样:
如果仅限于 POSIX 实用程序,您可以使用
awk
来进行大写:与 zsh 一样,它将遵循语言环境将文件名解码为文本,将字符分类为大写
alnum
并转换为大写。为了符合你的方法:
其他几点说明:
$(shell ...)
会被扩展至make
未经任何形式过滤的代码中,因此对于包含 Shell 语法中特殊字符(例如空格、;
、*
、'
等)的文件名,该扩展将不起作用。事实上,这是一个典型的任意代码执行漏洞案例。但话又说回来,在使用时,make
您必须放弃并希望安全可靠地执行任何操作。它实际上只应用于严格控制的数据(如果您能保证目录cmd
只包含您期望的文件,那么在这种情况下可能没问题)。echo
不能用于任意数据zsh
,包括 的sh
默认 shellmake
,参数扩展必须被引用以防止 split+glob,因此$${f}
应该是"$$f"
(或者"$${f}"
如果你愿意的话)。您的评论告诉我们:
\U
。您无需依赖 GNU sed,而是可以使用每个 Unix 机器上任何 shell 中的任何 awk 来执行此操作:
这是上述问题中的示例未涵盖的一些输入的运行情况,因此您可以决定输出是否可取:
要在 Makefile 中使用上述任一方法,
$0
需要成为$$0
并且 awk 脚本在逻辑上必须全部在 1 行上,因此您需要添加几个;
s 并在脚本中添加换行符,例如(未经测试):