Reputation: 38667
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
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
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
Reputation: 42999
Use awk
one-liner:
awk -F$'\t' -v OFS=$'\t' '{ $1 = toupper($1) }1' file
Upvotes: 1