更改每行第一个单词的大小写

Change case of first word of each line

从命令行,如何将文本文件中每行的第一个单词改为大写?

示例输入:

hello   world  
tell    me who you are!  

示例输出:

HELLO   world  
TELL    me who you are!  

没有空行,它是 ASCII,每行以一个字母单词开头,后跟一个 制表符

要使用的工具:任何在 macOS 命令行上运行的工具(bash 3.2、BSD sed、awk、tr、perl 5、python 2.7, swift 4, 等等).

使用awk一行:

awk -F$'\t' -v OFS=$'\t' '{  = toupper() }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[^ ]* \(.*\)/ /
}

您始终可以只使用 bash 大小写转换和 while 循环来完成您想要的,例如

$ while read -r a b; do echo "${a^^} $b"; done < file
HELLO world
HOW are you?

参数扩展 ${var^^}var中的所有字符转换为大写,${var^}转换第一个字母。

Bash 3.2 - 'tr'

对于早期的 bash,您可以使用与 tr 相同的设置和 herestring 来处理大小写转换:

$ while read -r a b; do echo "$(tr [a-z] [A-Z] <<<"$a") $b"; done file
HELLO world
HOW are you?

保留 \t 个字符

要保留制表符分隔的单词,您必须防止在阅读过程中出现单词拆分。不幸的是,read-d 选项不允许在一组字符上终止。一种检查 spacestab 分隔词的方法是读取整行禁用 IFS= 的分词,然后向前扫描该行直到第一个文字 $' '$'\t' 被发现。 (文字是 bash-only,不是 POSIX shell)一个简单的实现是:

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

tab 分隔词的输出

HELLO   world
HOW     are     you?