Skip to content

Instantly share code, notes, and snippets.

@aileftech
Created October 1, 2022 18:10
Show Gist options
  • Star 122 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save aileftech/dd4f5598b1f3837651fdf16e5abc3ffb to your computer and use it in GitHub Desktop.
Save aileftech/dd4f5598b1f3837651fdf16e5abc3ffb to your computer and use it in GitHub Desktop.
A Bash one-liner to produce a list of HEX color codes that read like (supposedly) valid English words
$ grep -P "^[ABCDEFabcdefOoIi]{6,6}$" /usr/share/dict/words | tr 'OoIi' '0011' | tr '[:lower:]' '[:upper:]' | awk '{print "#" $0}'
#ACAD1A
#B0BB1E
#DEBB1E
#AB1DED
#ACAC1A
#ACCEDE
#AC1D1C
#BAB1ED
#BA0BAB
#BEADED
#BEDDED
#BEEFED
#B0BBED
#B0D1CE
#B00BED
#CABBED
#CABB1E
#CADD1E
#C1CADA
#C0DDED
#C0FFEE
#C01FED
#DABBED
#DECADE
#DEC1DE
#DEC0DE
#DEEDED
#DEFACE
#DEF1ED
#DE1CED
#D0FFED
#D00DAD
#EDD1ED
#EFFACE
#FACADE
#F1BBED
#F0BBED
#0FF1CE
@aghasemi
Copy link

aghasemi commented Oct 1, 2022

Assuming 5 can be S:

#ABA51A
#ABA51C
#ABBA51
#ABBE55
#ACAC1A
#ACAD1A
#ACAD1E
#ACCEDE
#ACCE55
#ACED1A
#AC1D1C
#AD1CEA
#A55BAA
#A55E55
#A5515E
#BABB1E
#BAB1ED
#BACABA
#BACCAE
#BA0BAB
#BA501D
#BA551A
#BA551E
#BEADED
#BEB055
#BEDDED
#BEDEAD
#BEDEAF
#BE5CAB
#BE51DE
#BE551E
#B1AC1D
#B10515
#B0BBED
#B0BB1E
#B0D1CE
#B0D1ED
#B01DAE
#B00D1E
#B055ED
#CADD1E
#CADD1E
#CADD15
#CA5ABA
#CA5ABE
#CA5E1C
#CA551A
#CA551A
#CA551E
#CA551E
#CA5515
#CA5515
#CEB01D
#C1CADA
#C0BAEA
#C0BBED
#C0BCAB
#C0CC1D
#C0FFEA
#C0FFEE
#C01FED
#C055A5
#C0551D
#DAB01A
#DA551E
#DEBA5E
#DEBB1E
#DECADE
#DECE55
#DEC1DE
#DEC0DE
#DEC01C
#DEFACE
#DE1F1C
#DE5EED
#D1AC1D
#D1BA5E
#D1E515
#D110D0
#D10D1A
#D0BBED
#D0DDED
#D0DD1E
#D00DAB
#D00DAD
#D00D1A
#ECE51C
#ECE515
#EDDA1C
#EFFACE
#E051DE
#E5C0BA
#E50D1C
#FACADE
#FAC1E5
#FA5CE5
#FA5C1A
#FA5C10
#FA5C15
#F1A5C0
#F1C01D
#F1DFAD
#F055ED
#1B1CE5
#1DEAED
#10D1DE
#10D050
#151DAE
#0B5EDE
#0B5E55
#0FF1CE
#5ABECA
#5ACC05
#5CAB1D
#5EABEE
#5ECEDE
#5EEDED
#5EE5EE
#51BBED
#51C5AC
#515500
#50DA1C
#50DDED

@sicpier
Copy link

sicpier commented Oct 1, 2022

You can simplify a little bit the line:
grep -i "^[ABCDEFOIS]{6}$" /usr/share/dict/words | tr '[:lower:]' '[:upper:]' | tr 'OIS' '015' |awk '{print "#" $0}'

@asimjalis
Copy link

You can replace ABCDEF with A-F

@gabrielsroka
Copy link

@sicpier , I was just coming here to post something similar, but grep doesn't work on my Ubuntu distro. I'd need egrep or grep -P

@robsheldon
Copy link

robsheldon commented Oct 1, 2022

Do you like backslashes? Then sed is the tool for you:

sed -n 's/^[a-fios]\{6\}$/#\U&/p' /usr/share/dict/words | tr 'OIS' '015'

-n ignores non-matching lines; /#\U appends the # and upper-cases matching lines.

edit: forgot & could be used in place of a capturing expression.

@gabrielsroka
Copy link

gabrielsroka commented Oct 1, 2022

as html, static

<div style='background-color: #ACAD1A; width: 100px'>#ACAD1A</div>
<div style='background-color: #B0BB1E; width: 100px'>#B0BB1E</div>
<div style='background-color: #DEBB1E; width: 100px'>#DEBB1E</div>
<div style='background-color: #AB1DED; width: 100px'>#AB1DED</div>
<div style='background-color: #ACAC1A; width: 100px'>#ACAC1A</div>
<div style='background-color: #ACCEDE; width: 100px'>#ACCEDE</div>
<div style='background-color: #AC1D1C; width: 100px'>#AC1D1C</div>
<div style='background-color: #BAB1ED; width: 100px'>#BAB1ED</div>
<div style='background-color: #BA0BAB; width: 100px'>#BA0BAB</div>
<div style='background-color: #BEADED; width: 100px'>#BEADED</div>
<div style='background-color: #BEDDED; width: 100px'>#BEDDED</div>
<div style='background-color: #BEEFED; width: 100px'>#BEEFED</div>
<div style='background-color: #B0BBED; width: 100px'>#B0BBED</div>
<div style='background-color: #B0D1CE; width: 100px'>#B0D1CE</div>
<div style='background-color: #B00BED; width: 100px'>#B00BED</div>
<div style='background-color: #CABBED; width: 100px'>#CABBED</div>
<div style='background-color: #CABB1E; width: 100px'>#CABB1E</div>
<div style='background-color: #CADD1E; width: 100px'>#CADD1E</div>
<div style='background-color: #C1CADA; width: 100px'>#C1CADA</div>
<div style='background-color: #C0DDED; width: 100px'>#C0DDED</div>
<div style='background-color: #C0FFEE; width: 100px'>#C0FFEE</div>
<div style='background-color: #C01FED; width: 100px'>#C01FED</div>
<div style='background-color: #DABBED; width: 100px'>#DABBED</div>
<div style='background-color: #DECADE; width: 100px'>#DECADE</div>
<div style='background-color: #DEC1DE; width: 100px'>#DEC1DE</div>
<div style='background-color: #DEC0DE; width: 100px'>#DEC0DE</div>
<div style='background-color: #DEEDED; width: 100px'>#DEEDED</div>
<div style='background-color: #DEFACE; width: 100px'>#DEFACE</div>
<div style='background-color: #DEF1ED; width: 100px'>#DEF1ED</div>
<div style='background-color: #DE1CED; width: 100px'>#DE1CED</div>
<div style='background-color: #D0FFED; width: 100px'>#D0FFED</div>
<div style='background-color: #D00DAD; width: 100px'>#D00DAD</div>
<div style='background-color: #EDD1ED; width: 100px'>#EDD1ED</div>
<div style='background-color: #EFFACE; width: 100px'>#EFFACE</div>
<div style='background-color: #FACADE; width: 100px'>#FACADE</div>
<div style='background-color: #F1BBED; width: 100px'>#F1BBED</div>
<div style='background-color: #F0BBED; width: 100px'>#F0BBED</div>
<div style='background-color: #0FF1CE; width: 100px'>#0FF1CE</div>

@antler5
Copy link

antler5 commented Oct 1, 2022

For those of you with 256color terminals, here's one that shows each color:

sed -n 's/^[a-fios]\{6\}$/\U&/p' /usr/share/dict/words \
  | tr 'OIS' '015' \
  | gawk --non-decimal-data \
         '{print "\033[48;2;" \
                 ("0x"substr($0,1,2))+0 ";" \
                 ("0x"substr($0,3,2))+0 ";" \
                 ("0x"substr($0,5,2))+0 "m" \
                 "       \033[0m " \
                 $0}'

I thought about leaving the text inside each color block, but I'd want to invert the color for the text FG, which would take us even further from a "one-liner". I'm already wishing I could loop over each color-component inside the pipe, but I'd need to keep the hex form for the output:

# Save HEX, using it to replace awk's $0 at the end: 
sed -n 's/^[a-fios]\{6\}$/\U&/p' /usr/share/dict/words \
  | tr 'OIS' '015' \
  | { while read HEX; do \
        echo $HEX | fold -w2 | xargs -n3 bash -c 'printf "\033[48;2;%03d;%03d;%03dm      \033[0m '"$HEX"'\n" 0x$0 0x$1 0x$2'; \
      done; }

# Loop over components instead of passing printf 3 args, now without invoking bash:
sed -n 's/^[a-fios]\{6\}$/\U&/p' /usr/share/dict/words \
  | tr 'OIS' '015' \
  | { while read HEX; do \
        printf '\033[48;2;'; \
        echo $HEX | fold -w2 | xargs -I {} printf '%03d' 0x{} | fold -w3 | tr '\n' ';'
        printf 'm      \033[0m %s\n' "$HEX"; \
      done; }

# Re-introduce that messy sub-shell for fancy FG colors:
sed -n 's/^[a-fios]\{6\}$/\U&/p' /usr/share/dict/words \
  | tr 'OIS' '015' \
  | { while read HEX; do \
        printf '\033[48;2;'; \
        echo $HEX | fold -w2 | xargs -I {} printf '%03d' 0x{} | fold -w3 | tr '\n' ';'
        printf 'm\033[38;2;'; \
        echo $HEX | fold -w2 | xargs -I {} bash -c 'DEC=$(printf "%d" 0x'{}'); printf "%03d" "$((255 - DEC))"' | fold -w3 | tr '\n' ';'
        printf 'm %s \033[0m %s\n' "$HEX"; \
      done; }

I bet someone who knows Perl well could do an all-in-one.

@gabrielsroka
Copy link

as html, live

<div id=app></div>
<script src='https://gabrielsroka.github.io/webpages/scripts/enable1.js'></script>
<script>
/*
`words` is defined in enable1.js.
see also 
https://github.com/gabrielsroka/gabrielsroka.github.io/blob/master/webpages/scripts/enable1.js
https://code.google.com/archive/p/dotnetperls-controls/downloads
*/
app.innerHTML = words
    .filter(w => w.match(/^[a-fios]{6}$/))
    .map(c => `<div style='background-color: #${c.replace(/o/g, '0').replace(/i/g, '1').replace(/s/g, '5')}; width: 100px'>#${c}</div>`)
    .join('');
</script>

@jaysoffian
Copy link

jaysoffian commented Oct 1, 2022

All in bash:

#!/usr/bin/env bash
shopt -s nocasematch
while read -r word; do
    if [[ $word =~ ^[abcdefoi]{6,6}$ ]]; then
        word=${word//o/0}
        word=${word//i/1}
        word=${word^^}
        printf '#%s\n' "$word"
    fi
done < /usr/share/dict/words

@karakfa
Copy link

karakfa commented Oct 2, 2022

here is an all awk version, slightly more readable than the sed version

awk '{$0=toupper($0)} /^[A-FOI]{6,6}$/{gsub("I",1); gsub("O",0); print "#" $0}' file

@antler5
Copy link

antler5 commented Oct 2, 2022

Pretty gosh darn happy with this now c:

Not pure bash, I think that the coreutils's conciseness (tr, fold, xargs) is indispensable and grep is just so much faster (something does feel a little slow, donno if it's the sub-shells, or the arrays, haven't put my finger on it). I think it's concise, and clear... so long as one knows <<<, <(), IFS, and overlooks the entire BG_RGB pipeline (for which one ought to know a relatively obscure feature of printf, xargs, and (new to me) fold). Gotta love shell.

while read -r WORD; do
  while read -r HEX; do
    IFS=" "
    read -r -a BG_RGB <<< "$(fold -w2 <<< $HEX | xargs -I {} printf '%d ' 0x{})"
    read -r -a FG_RGB <<< "$(for component in ${BG_RGB[*]}; do printf '%d ' $((255 - $component)); done)"
    IFS=";"
    printf '\033[48;2;'"${BG_RGB[*]}"'m\033[38;2;'"${FG_RGB[*]}"'m '"$HEX"' \033[0m %s\n'
  done < <(tr 'IOS' '105' <<< ${WORD^^})
done < <(grep -Pi "^[A-FIOS]{6,6}$" /usr/share/dict/words)
# time for a in {1..10}; do ... ; done
# real  0m7.699s
# user  0m8.047s
# sys   0m1.301s

Edit:

something does feel a little slow

It was xargs, 'bout 50% faster without it (specifically not because of any other change I made to refactor it out, though most tweaks do push it over real 0m4s).

while read -r WORD; do
  while read -r HEX; do
    IFS=$'\n'
    BG_RGB=( $(fold -w2 <<< $HEX | while read -r COMP; do printf '%d\n' 0x$COMP; done) )
    FG_RGB=( $(for COMP in ${BG_RGB[*]}; do printf '%d\n' $((255 - $COMP)); done) )
    IFS=";"
    printf '\033[48;2;'"${BG_RGB[*]}"'m\033[38;2;'"${FG_RGB[*]}"'m '"$HEX"' \033[0m %s\n'
  done < <(tr 'IOS' '105' <<< ${WORD^^})
done < <(grep -Pi "^[A-FIOS]{6,6}$" /usr/share/dict/words)
# time for a in {1..10}; do ... ; done
# real  0m3.908s
# user  0m3.711s
# sys   0m0.716s

Edit: sed is slightly faster than grep or awk (for matching words, on my machine), and dropping the nested while loop into what is now sed's pipeline saves a ton of time. This is as fast as I think it gets, at least without using awk or sed for more than just what grep can do.

while read -r HEX; do
  IFS=$'\n'
  BG_RGB=( $(fold -w2 <<< $HEX | while read -r COMP; do printf '%d\n' 0x$COMP; done) )
  FG_RGB=( $(for COMP in ${BG_RGB[*]}; do printf '%d\n' $((255 - $COMP)); done) )
  IFS=";"
  printf '\033[48;2;'"${BG_RGB[*]}"'m\033[38;2;'"${FG_RGB[*]}"'m '"$HEX"' \033[0m %s\n'
done < <(sed -n 's/^[A-FIOSa-fios]\{6\}$/\U&/p' /usr/share/dict/words | tr 'IOS' '105') \
# time for a in {1..10}; do ... ; done
# real	0m2.318s
# user	0m2.227s
# sys	0m0.464s

Edit: I gotta go to bed :c
But just as a quick and dirty point of comparison, has an (extra) advantage bc the loop is unrolled (not that it makes a difference):

#!/usr/bin/env -S awk --non-decimal-data -f
{$0=toupper($0)}
/^[A-FIOS]{6,6}$/ {
  gsub("I",1);
  gsub("O",0);
  gsub("S",5);
  print "\033[48;2;" \
        000+("0x"substr($0,1,2)) ";" \
        000+("0x"substr($0,3,2)) ";" \
        000+("0x"substr($0,5,2)) "m" \
        "\033[38;2;" \
        255-("0x"substr($0,1,2)) ";" \
        255-("0x"substr($0,3,2)) ";" \
        255-("0x"substr($0,5,2)) "m" \
        " #" $0 \
        " \033[0m"; }
# time for a in {1..10}; do ... ; done
# real	0m0.539s
# user	0m0.532s
# sys	0m0.008s

@dainiuxt
Copy link

dainiuxt commented Oct 2, 2022

Where is #BADA55 (or this is clean version)?

@gabrielsroka
Copy link

@reverofevil
Copy link

image

@lucasqueiroz
Copy link

What if you take into account hex codes with 3 characters?

@mcjcloud
Copy link

image

@lucasqueiroz

#AAA
#ABC
#ABE
#ACE
#ADA
#ADD
#AD0
#A1D
#A55
#BAD
#BBC
#BED
#BEE
#B1B
#B1D
#B0A
#B0B
#B00
#B5C
#CAB
#CAD
#CB1
#C1D
#C0B
#C0D
#C00
#C05
#DAB
#DAD
#DEB
#DFC
#D1D
#D1E
#D0C
#D0E
#D5C
#EBB
#E5C
#E5E
#FAD
#FED
#FEE
#F1B
#F0B
#F0E
#1B1
#1CE
#1DA
#111
#0AF
#0DD
#0DE
#0ED
#0FF
#5AD
#5EA
#5EC
#5EE
#51C
#50B
#50D
#55E

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment