I need all 2-3 character words completely capitalized. 1 character and 4+ character words need to be remain untouched.
Input:
cat Example
Dog
I
Fish
su
Su adm
Amd Cat ignore
Expected output:
CAT Example
DOG
a
Fish
SU
SU ADM
ADM CAT ignore
Using GNU sed
$ sed -E 's/\<[[:alpha:]]{2,3}\>/\U&/g' input_file
DOG
I
Fish
SU
SU ADM
AMD CAT ignore
sed
even handles unicode correctly!? I tried your solution with a file containing the string sté
and it correctly converted it to STÉ
!
I would use perl instead:
$ perl -pe 's/\b\w{2,3}\b/uc($&)/eg' file
CAT Example
DOG
I
Fish
SU
SU ADM
AMD CAT ignore
If your file contains non-ASCII characters encoded in UTF-8 and your locale uses UTF-8 as the charmap, for example the string sté
that should become STÉ
, then use:
$ perl -C -pe 's/\b\w{2,3}\b/uc($&)/eg' file
CAT Example
DOG
I
Fish
SU
SU ADM
AMD CAT ignore
STÉ
perl -pe's/\b\w{2,3}\b/\U$&/g'
, note that \w
also matches on ASCII digits and underscores and only matches on ASCII letters. It would turn Stéphane
to STéphane
for instance.
Commented
Jul 29, 2022 at 11:17
\U
doesn't work for me, I always use uc()
so I don't know why it fails, but it seems to be explecting a package: Can't locate object method "U" via package "cat" (perhaps you forgot to load "cat"?) at -e line 1, <> line 1.
but using $&
avoids the need for a capture group, so I added that. I also added a unicode aware version, thanks!
U
, got it. Thanks @StéphaneChazelas!
This is a solution with awk:
awk '{ for (i=1; i<=NF; i++) { if (length($i) <= 3) { $i=toupper($i) } } }1' infile
Using Raku (formerly known as Perl_6)
raku -pe 's:g/<?wb> \w**2..3 <?wb>/{$/.uc}/;'
OR
raku -pe 's:g/<|w> \w**2..3 <|w>/{$/.uc}/;'
OR
raku -pe 's:g/<< \w**2..3 >>/{$/.uc}/;'
The Raku code above is a fairly direct translation of @terdon's Perl code. Word boundaries are written either <?wb>
or <|w>
in Raku. These can be negated as <!wb>
or <!|w>
, respectively. In the last example, a left word-boundary is <<
and a right word boundary is >>
. Raku's match variable is $/
, which can also be spelled $<>
.
You can change the target class from \w
to <alpha>
or <alnum>
or even to <:Letter>
(abbreviated <:L>
). Nota bene: \w
and <alpha>
and <alnum>
will match underscore while <:Letter>
and <:L>
will not.
All the classes mentioned immediately above are Unicode-aware so any sort of "case-folding" shouldn't be a problem. You can write regexes targeting Unicode-defined <:Ll>
lowercase letters and/or Unicode-defined <:Lu>
uppercase letters, and you can even compare letters with the .fc
"foldcase" routine.
Sample Input:
cat Example
Dog
I
Fish
su
Su adm
Amd Cat ignore
sté
a
Xa
Xá
Xå
Xà
Xä
Xb
Xß
Xœ
Xþ
Sample Output:
CAT Example
DOG
I
Fish
SU
SU ADM
AMD CAT ignore
STÉ
a
XA
XÁ
XÅ
XÀ
XÄ
XB
XSS
XŒ
XÞ
https://docs.raku.org/language/regexes#Anchors
https://raku.org
Let's
be converted toLET's
,LET'S
or not converted. How aboutIt's
ori'm
? IOW, how do you define word?a
is a better example than the uppercase letterI
?