Cœur
Cœur

Reputation: 38667

Change case of first word of each line

From command line, how to change to uppercase each first word of a line in a text file?

Example input:

hello   world  
tell    me who you are!  

Example output:

HELLO   world  
TELL    me who you are!  

There are no empty lines, it's ASCII, and each line starts with an alphabetic word followed by a tab.

Tools to use: anything that works on command line on macOS (bash 3.2, BSD sed, awk, tr, perl 5, python 2.7, swift 4, etc.).

Upvotes: 2

Views: 1728

Answers (3)

David C. Rankin
David C. Rankin

Reputation: 84561

You can always just use bash case conversion and a while loop to accomplish what you intend, e.g.

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

The parameter expansion ${var^^} converts all chars in var to uppercase, ${var^} converts the first letter.

Bash 3.2 - 'tr'

For earlier bash, you can use the same setup with tr with a herestring to handle the case conversion:

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

Preserving \t Characters

To preserve the tab separated words, you have to prevent word-splitting during the read. Unfortunately, the -d option to read doesn't allow termination on a set of characters. A way around checking for both spaces or tab delimited words is the read the entire line disabling word-splitting with IFS= and then scanning forward through the line until the first literal $' ' or $'\t' is found. (the literals are bash-only, not POSIX shell) A simple implementation would be:

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

Output of tab Separated Words

HELLO   world
HOW     are     you?

Upvotes: 2

etopylight
etopylight

Reputation: 1319

Using GNU sed:

sed 's/^\S*/\U&/g' file

where \S matches a non-whitespace character and \U& uppercases the matched pattern

UPDATE: in case of BSD sed since it does not support most of those special characters it is still doable but requires a much longer expression

sed -f script file

where the script contains

{
    h
    s/ .*//
    y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/
    G
    s/\(.*\)\n[^ ]* \(.*\)/\1 \2/
}

Upvotes: 1

codeforester
codeforester

Reputation: 42999

Use awk one-liner:

awk -F$'\t' -v OFS=$'\t' '{ $1 = toupper($1) }1' file

Upvotes: 1

Related Questions