我有一个 Markdown 文档myfile.md
,其中包含英语句子列表,其中一些首字母小写,一些首字母大写。
所有英文句子均以标准英文字母开头;不使用特殊字符:
x
x
x
我需要一个符合该逻辑的函数:
如果任何第一个英文字母是小写,则将其大写
因此,要将文件更改为如下所示:
X
X
X
我尝试过的
1)tr
我想尝试使用tr
正则表达式来做到这一点,'tr '[:lower:]' '[:upper:]' myfile.md
但我既没有找到一种将正则表达式组合在 中的方法tr
,也没有找到一种用 来处理文件内数据的方法tr
。
相反,我只找到了一种在 shell 提示符中转换文本的方法,如下所示:
echo x | tr '[:lower:]' '[:upper:]'
X
2)sed
sed 's/^[a-z]*/[A-Z]/' myfile.md
sed -r 's/^[a-z]*/[A-Z]/' myfile.md
但执行后,myfile.md
仍然包含
x
x
x
反而:
X
X
X
我的问题
如何在不使用任何 CLUI 文本编辑器(例如nano
或)的情况下使用 shell 中描述的逻辑vim
?
答案1
使用\U
GNU sed 中的函数。
s/^\([a-z]\)/\U\1/
因此,如果该字符是小写,则捕获行开头的单个字符,如果该字符是大写,则捕获该字符。
由于 \U 不理会其他事物,因此可以简化为
s/\(.\)/\U\1/
因为.
将会匹配该行的第一个字符(如果有)。
答案2
tr
在这里不会帮助你,因为大写的tr
会变成全部字符转换为大写(tr
仅具有一次字符上下文,因此它永远不会知道“行首”或“单词开头”)。
sed
如果你使用 GNU 就可以做到sed
。但是,您显示的方式将用文字文本替换第一个大写字符[A-Z]
。
由于这个问题被标记为POSIX,这是一个符合标准的awk
解决方案,它将简单地将任意行上的第一个字符大写:
awk '{ ch = toupper(substr($0,1,1)); sub(".", ""); $0 = ch $0; print }' file
该awk
命令正在执行的操作是使用 提取该行的第一个字符substr()
。然后将其大写并将其分配给变量ch
。然后使用删除该行上的第一个字符sub()
,并将大写字母ch
添加到该行前面。然后打印该行。
测试这个:
$ cat file
Apple
orange
grapefruit
Mango
$ awk '{ ch = toupper(substr($0,1,1)); sub(".", ""); $0 = ch $0; print }' file
Apple
Orange
Grapefruit
Mango
如果数据有一些缩进(即行开头有空格),则使用
awk '{ ch = toupper(substr($1,1,1)); sub(".", "", $1); $1 = ch $1; print }' file
(但这会消除缩进)。
如果您愿意使用 Perl 来执行此操作,则以下代码会将每行的第一个字符大写,其方式与awk
上面第一个程序的执行方式类似。
perl -pe 'substr($_,0,1,uc(substr($_,0,1)))' file
虽然使用
perl -pe 's/^./\U$&/' file
会更短并且更“像 Perl”。
^.
在该表达式中替换[^[:blank:]]
为 来替换该行中的第一个非空白字符(这将保存任何缩进)。
答案3
答案4
POSIX sed:
h
s/(.).*/\1/
y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/
G
s/(.)\n.?(.*)/\1\2/