例如,我有一个 shell 变量。 a=“大个子小男人”。如何在 bash 中使用正则表达式打印出仅中间单词大写的变量? (大人小人)
我可以通过将变量分成 3 个变量,然后在 echo 中扩展它们来做到这一点。例如first=${a%* }
,等等。但是我如何使用一个正则表达式一次性完成它?
是否可以在一行中完成?使用大写运算符 (^)
答案1
sed
假设您使用 GNU sed:
$ sed -E 's/(\w+) (\w+) (\w+)/\1 \U\2\E \3/' <<< 'big little man'
big LITTLE man
该命令利用GNU 特定序列 \U
和\E
分别将后续字符转为大写并取消大小写转换。
awk
虽然不对正则表达式进行操作,但awk
提供了另一种将单个单词大写的便捷方法:
$ awk '{print($1, toupper($2), $3)}' <<< 'big little man'
big LITTLE man
巴什
尽管 Bash 本身没有基于正则表达式的转换,但您仍然可以通过将字符串视为数组来实现部分大写,例如
$ (read -a words; echo "${words[0]} ${words[1]^^} ${words[2]}") <<< 'big little man'
big LITTLE man
这里^^
将数组的第二个元素(即第二个单词)转换为大写。该功能是在 Bash 4 中引入的。
答案2
根据要求,bash
使用以下命令在一行中执行此操作${variable^^}
:
$ a="big little man"
$ [[ "$a" =~ ^([^ ]+)\ ([^ ]+)\ (.*) ]] && a="${BASH_REMATCH[1]} ${BASH_REMATCH[2]^^} ${BASH_REMATCH[3]}"
$ echo "$a"
big LITTLE man
这将正则表达式([^ ]+)\ ([^ ]+)\ (.*)
与 中的字符串进行匹配$a
。如果匹配,则它包含三个用空格分隔的子字符串。第一个和第二个子字符串将是不包含空格的任何字符串,第三个子字符串将是字符串的剩余位。
如果表达式匹配,则$a
使用大写的第二个子字符串重写该值。
这假设原始字符串以非空格字符开头。
答案3
我不认为你可以用bash
扩展操作符一次性做到这一点。你可以用zsh
's:
set -o extendedglob # for (#m)
b=${a/(#m) * /${(U)MATCH}}
或者:
b=${(S)a/(#b)(*) (*) (*)/$match[1] ${(U)match[2]} $match[3]}
在哪里:
(#m)
导致匹配的字符串可用$MATCH
(#b)
启用反向引用${(U)var}
(也$var:u
) 变为大写(比bash
s早${var^^pattern}
几十年)。(S)
打开非贪婪匹配。