String 更改每行第一个字的大小写
在命令行中,如何将文本文件中每行的第一个单词改为大写? 输入示例:String 更改每行第一个字的大小写,string,bash,awk,uppercase,String,Bash,Awk,Uppercase,在命令行中,如何将文本文件中每行的第一个单词改为大写? 输入示例: hello world tell me who you are! 示例输出: HELLO world TELL me who you are! 没有空行,它是ASCII码,每一行都以字母开头,后跟一个选项卡 要使用的工具:任何在macOS上的命令行上工作的工具(Bash3.2、BSDSED、awk、tr、Perl5、Python2.7、swift 4等)。使用awk一行程序: awk -F
hello world
tell me who you are!
示例输出:
HELLO world
TELL me who you are!
没有空行,它是ASCII码,每一行都以字母开头,后跟一个选项卡
要使用的工具:任何在macOS上的命令行上工作的工具(Bash3.2、BSDSED、awk、tr、Perl5、Python2.7、swift 4等)。使用
awk
一行程序:
awk -F$'\t' -v OFS=$'\t' '{ $1 = toupper($1) }1' file
使用
GNU sed
:
sed 's/^\S*/\U&/g' file
其中,\S
匹配非空白字符,\U&
大写匹配的模式
更新:对于BSD sed
而言,由于它不支持大多数特殊字符,因此仍然可行,但需要更长的表达式
sed -f script file
脚本中包含
{
h
s/ .*//
y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/
G
s/\(.*\)\n[^ ]* \(.*\)/\1 \2/
}
您总是可以使用bash case转换和while循环来完成您想要的,例如
$ while read -r a b; do echo "${a^^} $b"; done < file
HELLO world
HOW are you?
保留\t
字符
HELLO world
HOW are you?
要保留制表符分隔的单词,必须防止在读取过程中拆分单词。不幸的是,读取
的-d
选项不允许在一组字符上终止。检查空格
或选项卡
分隔词的一种方法是读取整行,使用IFS=
禁用分词,然后向前扫描整行,直到找到第一个文本$'
或$'\t'
。(文本仅限于bash,而不是posixshell)一个简单的实现是:
while IFS= read -r line; do
word=
ct=0
for ((i = 0; i < ${#line}; i++)); do
ct=$i
## check against literal 'space' or 'tab'
[ "${line:$i:1}" = $' ' -o "${line:$i:1}" = $'\t' ] && break
word="${word}${line:$i:1}"
done
word="$(tr [a-z] [A-Z] <<<"$word")"
echo "${word}${line:$((ct))}"
done <file
谢谢,它适用于后跟空格的单词。但实际上,我发现我的数据是表格而不是空格。你知道如何避免用空格替换制表符吗?只是更新了答案,以便
awk
将空格和制表符都视为分隔符。好的,我终于找到了一个完全适用于制表符的解决方案:awk-F$'\t'{OFS=“\t”}{$1=toupper($1)}1'
您可以通过-v
选项实现同样的效果-更新了答案。我认为这就解决了问题的方法,sed
,awk
,bash
——包括在内。抱歉,没有注意到它应该出现在macOS上。为BSD sed
和GNU sed
添加了通用方法。我同意当GNU-sed
不可用时,awk
脚本会更干净。哦,对不起,是的,这对于案例转换扩展来说还早了一点:)
@Cœur如果出于任何原因3.2没有herestring,您可以使用$(echo“$a”[a-z][a-z])
,但最好避免使用管道。sed
或awk
如果必须使用tr
会更快。参数扩展速度非常快,但是如果您要调用tr
数千次,这可能是流编辑器sed
的工作<代码>:)记住每个命令替换(例如,$(..)
),并且对tr
的每次调用都会产生单独的子shell。(我很好奇你的时间sed…
和时间awk…
比较…)你用tr
的解决方案很好,但它用空格代替了制表符。是的,这是读取时发生的分词限制。可以使用IFS
(内部字段分隔符)控制,也可以通过使用字符串索引向下爬行字符串来分隔选项卡
和空格
。您可以简单地读取-r行
,然后for((i=0;i<${line};i++);如果[“${line:$i;1}”=''']| |[“${line:$i:1}”='\t'];然后word=“${line:0:$((i-1))}”;打破fi;完成
,然后只需选中“$word”!=“$line”
并在$word
上使用tr
。明天早上我会更新答案——已经很晚了。:)
HELLO world
HOW are you?