我想转换这个:
foo^bar
ba^rfoo
oofrab
raboof^
对此:
FOObar
BArfoo
oofrab
RABOOF
“^”(或其他特殊字符,如果方便的话)之前的任何字符都大写
此外,如果这样做更容易的话,也不需要删除“^”。
答案1
使用 GNU sed
(Ubuntu 的默认设置)(感谢 pabouk 提供的-r
选项建议):
< inputfile sed -r 's/^(.*)\^/\U\1\E/' > out
使用perl
(感谢 Oli 提供的缩短正则表达式):
< inputfile perl -pe 's/^(.*)\^/\U\1\E/' > out
命令 #1 分解:
< inputfile
:将内容重定向inputfile
至stdin
-r
:允许使用扩展正则表达式> out
:将内容重定向stdout
至out
命令 #2 分解:
< inputfile
:将内容重定向inputfile
至stdin
> out
:将内容重定向stdout
至out
正则表达式细分:
s
:执行替换/
: 启动正则表达式^
: 匹配行首(
:开始第一个捕获组.*
: 匹配任意数量的字符)
:停止第一个捕获组\^
: 匹配一个^
字符/
:停止正则表达式/开始替换\U
: 开始转换为大写\1
: 替换为第一个捕获组\E
: 停止转换为大写/
:停止替换
答案2
使用vim
:
vim -es '+g/\^/normal gUf^' +wq foo
- 打开
-es
令人尊敬的 ex 模式,并使 vim 静音(大部分)。 +
用于提供 vim 命令作为命令行参数。g/\^/
- 在所有匹配的行上运行命令/\^/
normal
- 将命令的其余部分作为正常模式操作运行。gUf^
- 转换为大写(gU
)直到^
(f^
)。在这种情况下使用范围时g/.../
,在执行命令之前,光标将放在每行的开头。- 然后保存并退出(
wq
)。
f
查找第一个^
,因此具有多个 的行将^
仅转换字段。没有简单的动作可以找到最后一个^
。您可以尝试转到行尾并向后搜索($F^
),但如果是最后一个字符,则该操作将失败^
。因此,您需要分两步进行:
vim -es '+g/\^./norm $F^gU0' '+g/\^$/norm gU$' +wq foo
答案3
编辑
大约一个半小时后,我想到了这个:
awk -F' ' '{ gsub(/\^/,"@ "); for (i=1;i<=NF;i++){ if($i ~ /\@/) $i = toupper($i);};gsub("@ ","");gsub("@",""); print } ' removecharsfile
基本思想:
- 删除 ^ 并用 @ 加空格替换
- 将空格视为字段分隔符;现在我们有字段可以使用了
- for 循环遍历每一行中的每个字段,并检查是否有 @ 字符。
- 如果有 @ 字符,则将该字段转换为大写。为什么 $i = toupper($i) ?因为否则它不会存储在任何地方
- 循环完成后,删除@+空格,以及字段末尾的任何@。
- 打印所有内容
也许将所有这些写在一行上的更好方法是将其放在一个文件中(整齐地组织在下面),然后像这样用 awk 运行它awk -f awkscript theinputfile
# awk script to capitalize
# whatever comes before caret(^)
{
gsub (/\^/, "@ ");
for (i = 1; i <= NF; i++)
{
if ($i ~ /\@/)
$i = toupper ($i);
};
gsub ("@ ", "");
gsub ("@", "");
print
}
实际运行如下:
原始帖子
我将用 awk 贡献我自己的代码版本:
awk -F'^' '{print toupper($1)$2}' thefile
当然,您可以使用> output.txt
以下方法重定向输出:
答案4
Bash 也可以做到这一点,因此我将把 bash 答案加入到其中。
#bash
while IFS= read -r line; do
if [[ $line = *^* ]]; then
tmp=${line%%^*}
line=${tmp^^}${line#*^}
fi
printf '%s\n' "$line"
done < inputfile > outptufile
这只是逐行迭代输入文件(Bash常见问题 1),并使用参数扩展进行拆分和大写(Bash常见问题 73)。