【问题标题】:How to uppercase the first char of a substring only if it has more than 3 chars length仅当子字符串的长度超过 3 个字符时,如何将子字符串的第一个字符大写
【发布时间】:2019-06-11 04:27:34
【问题描述】:

我需要转换这个字符串:

我的名字是来自这里而不是那里的用户。

到:

我的名字用户来自这里不是那里

详细信息是,我需要对任何超过 3 个字符的单词的第一个字符进行字符串处理。只是它。我正在尝试使用以下命令但没有成功:

echo $FOO | tr '[:upper:]' '[:lower:]' | sed -e "s/\b\(.\)/\u\1/g"

其他的都应该小写。

【问题讨论】:

  • 虽然看到您的个人资料后知道您从未选择任何答案作为正确答案,但请在某个时间给出它,当您有一些答案时,也尝试选择其中任何一个作为正确答案。
  • 您的问题标题说超过 2,但正文询问超过 3。请edit 保持一致,或澄清。
  • 感谢您的反馈,我的问题表述不当,我想现在更清楚了。关于选择正确答案RavinderSingh13,你是对的,但在我的老问题中我仍在寻找更多答案,因为他们都无法解决问题,但我想现在没有人会回答。

标签: sed tr


【解决方案1】:

请您尝试关注一下。

echo "my name is user from here not there." |
awk '{for(i=1;i<=NF;i++)
    if(length($i)>3){$i=toupper(substr($i,1,1)) substr($i,2)}}
    1'

结果:

my Name is User From Here not There.

【讨论】:

  • 感谢@tripleee 编辑它,我忘了添加单行形式的解决方案。
  • 谢谢!工作正常,除了第一个单词应该有大写的第一个字符。
【解决方案2】:

使用 GNU sed,(和bash):

F="my name is user from here not there."
sed -E 's/^./\u&/;s/([[:space:]])([[:alpha:]]{4})/\1\u\2/g' \ 
    <<< "${F,,}"

或:

sed -E 's/^./\u&/;s/(\s)(\w{4})/\1\u\2/g' <<< "${F,,}"

输出:

My Name is User From Here not There.

注意事项:

"${F,,}" 是一个bash case modification parameter expansion,它返回一个小写版本的$F,它成为sed 的输入。

GNU sed 为常见的regex 字符类提供了一些有用的synonyms and abbreviations。字符类[a-zA-Z0-9_]可以缩写为[[:alpha:]_],或者更简单的\w

尽管\u 看起来像一个regex 缩写,但它不是。这是一个"special sequence",仅用于substitute 命令替换文本——\u 表示“将下一个字符转为大写”

&amp; 指的是 substitute 命令中匹配的第一个 regexp。比较以下:

sed 's/./&/'          <<< foo  # outputs "f"
sed 's/./&/g'         <<< foo  # outputs "foo"
sed 's/./&&&&/g'      <<< foo  # outputs "ffffoooooooo"
sed 's/./\u&&&\u&/g'  <<< foo  # outputs "FffFOooOOooO"
sed 's/.*/&&&&/'      <<< foo  # outputs "foofoofoofoo"

有关详细信息,请参阅GNU sed info pages

【讨论】:

  • 完美!我必须先添加tr '[:upper:]' '[:lower:]',而不是使用您的解决方案,否则它不会像我需要的那样通才。我确实在 sed 文档中进行了搜索,但我无法理解这些组是如何工作的 (\w{4}) \b、\u、\s,例如为什么在 \u 之后使用斜杠和数字,或者 &。 \w 表示任何单词?就像正则表达式?你能解释一下吗?
  • @Otavio,请参阅修订后的更一般性的答案——应该不再需要添加 tr
  • 谢谢!使用你在笔记中所说的,我将突击队恢复到echo $SENTENCE | sed -E 's/./\l&amp;/g;s/^./\u&amp;/;s/(\b)(\w{4})/\1\u\2/g'。不使用 tr。想用pearl,方便携带,正如triplee所说,但没有成功。
【解决方案3】:

tr 并不是真正适合这项工作的工具;它根本不知道上下文。

sed 的某些变体具有 Perl 或 vi 正则表达式扩展,但这也不能通过 sed 真正可移植地解决。

Perl 的救援:

bash$ foo="my name is user from here not there."

bash$ echo "$foo" | perl -pe 's/\w{4,}/\u$&/g'
my Name is User From Here not There.

这可以满足您的实际要求,但不是您想要的。也许添加一个条件来分别大写输入的第一个单词......或者切换到像Lingua::EN::Titlecase这样的库。

还要注意我们如何do not use upper case for our private variables(因为大写变量保留给系统使用)和always quote our shell strings.

【讨论】:

  • 工作正常,除了你说的第一个词。 Perl 似乎是替换 sed 的好选择,因为我希望将来在 mac osx 中使用这些脚本。感谢您的回答!
  • 将正则表达式更改为 ^\w+|\w{4,} 如果您愿意,也可以将任何首字母大写。
【解决方案4】:

这可能对你有用(GNU sed):

sed -E 's/^\w+|\b\w{4,}\b/\u&/g' file

如果该单词出现在以某个单词或任何 4 个或更多字符长的单词开头的行中,则该单词的第一个字符大写

【讨论】:

  • 乍一看这似乎与my sed answer 没有太大不同,但| 和单次替换是明显的改进。一个调整——用^.替换^\w+,它仍然有效。
  • 效果很好。正如我在 agc 回答中所说,在应用您的 sed 过滤器之前,我必须将所有内容都小写,否则像 My NAME IS NOT sMITH 这样的句子将不起作用。对不起我的无知。直到最后一个 \b 我才明白,但是 \u& 是如何工作的?我尝试了很多不同的组合,但都没有成功。
  • @Otavio \u&amp; 将替换命令的 LHS 中匹配的字符串的第一个字符变为大写。
猜你喜欢
  • 2012-06-09
  • 1970-01-01
  • 2013-09-27
  • 1970-01-01
  • 2011-05-03
  • 2020-07-02
  • 2022-06-21
  • 2020-01-10
  • 1970-01-01
相关资源
最近更新 更多