例如我有一句话:你的房子号码是多少?是 iT 26。我必须将每个单词的所有第一个第一个字母都转换为大写并以小写形式保留。我想使用所有lsearch、lindex lreplace和东西并形成代码。有人可以告诉我该怎么做吗?
3 回答
该string totitle
命令关闭:它将整个字符串小写,但第一个字符为大写。
set s {whAT is yOur hoUSe nUmBer ? Is iT 26.}
string totitle $s
What is your house number ? is it 26.
将每个单词大写要复杂一些:
proc CapitalizeEachWord {sentence} {
subst -nobackslashes -novariables [regsub -all {\S+} $sentence {[string totitle &]}]
}
set s {whAT is yOur hoUSe nUmBer ? Is iT 26.}
CapitalizeEachWord $s
What Is Your House Number ? Is It 26.
regsub 命令获取每个以空格分隔的单词并将其替换为文字字符串“[string totitle word ]”:
"[string totitle whAT] [string totitle is] [string totitle yOur] [string totitle hoUSe] [string totitle nUmBer] [string totitle ?] [string totitle Is] [string totitle iT] [string totitle 26.]"
我们使用该subst
命令来评估所有单独的“string totitle”命令。
当 Tcl 8.7 发布时,我们将能够:
proc CapitalizeEachWord {sentence} {
regsub -all -command {\S+} $sentence {string totitle}
}
将命令应用于字符串的一堆正则表达式选择的子字符串的常用模型(在 8.6 和之前)是这样的:
subst [regsub -all $REtoFindTheSubstrings [MakeSafe $input] {[TheCommandToApply &]}]
之所以需要,MakeSafe
是因为subst
不只是做你想要的。即使禁用了一些替换类(例如,使用-novariables
)选项,您仍然需要最棘手的一个——命令替换——这意味着类似的字符串hello[pwd]goodbye
可以让你措手不及。为了解决这个问题,您可以通过将每个 Tcl元字符(或至少在 a 中重要的元字符)替换subst
为其反斜杠版本来使字符串“安全”。这是一个经典版本MakeSafe
(您经常会看到内联):
proc MakeSafe {inputString} {
regsub -all {[][$\\{}"" ]} $inputString {\\&}
}
以交互方式演示它:
% MakeSafe {hello[pwd]goodbye}
hello\[pwd\]goodbye
使用该版本,尽管您可以关闭变量,但无需关闭替换类subst
,并且当您应用命令时不会有任何意外,因为可能出现在替换参数字符串中的内容已被转义。但是有一个很大的缺点:您可能需要更改转换中的正则表达式以考虑现在存在的额外反斜杠。问题的 RE 不需要它(因为它只是选择单词字符序列),实际上可以安全地使用这个简化版本:
subst [regsub -all {\w+} [regsub -all {[][\\$]} $input {\\&}] {[string totitle &]}]
从 8.7 开始,有一个-command
选项regsub
可以避免所有这些混乱。它也快了很多,因为subst
它通过将其转换编译成字节码来工作(这对于一次性替换来说不是一个好的胜利!)并regsub -command
使用直接命令调用来代替,更有可能更快。
regsub -all -command {\w+} $input {string totitle}
使用的内部方法regsub -all -command
可以在 8.6 中进行模拟(或更早版本使用更多额外的垫片),但它并非微不足道:
proc regsubAllCommand {RE input command} {
# I'll assume there's no sub-expressions in the RE in order to keep this code shorter
set indices [regexp -all -inline -indices -- $RE $input]
# Gather the replacements first to make state behave right
set replacements [lmap indexPair $indices {
# Safe version of: uplevel $command [string range $input {*}$indexPair]
uplevel 1 [list {*}$command [string range $input {*}$indexPair]]
}]
# Apply the replacements in reverse order
set output $input
foreach indexPair [lreverse $indices] replacement [lreverse $replacements] {
set output [string replace $output {*}$indexPair $replacement]
}
return $output
}
C 实现regsub
在内部使用工作缓冲区等,但这在 Tcl 级别上不太方便。
您可以使用 Initcap 函数将第一个字母设为大写,其余字母设为小写。