You are not logged in.
Pages: 1
I want to write a bash script that creates word arts. The script should allow the user to write a sentence and then take that sentence break it down to letters and convert the letters based on predefined variables that we can set at the beginning of the Script .
I already have three types of styles (full alphabet sets) so we can define the alphabetics from A to Z via the Script For The Three Styles.
The Script should be able to recognize spaces as well.
This is what I have so far:
#!/bin/bash
# Define the alphabet for each style
style1="a= b= c= d= e= f= g= h= i= j= k= l= m= n= o= p= q= r= s= t= u= v= w= x= y= z= "
style2="a= b= c= d= e= f= g= h= i= j= k= l= m= n= o= p= q= r= s= t= u= v= w= x= y= z= "
style3="a= b= c= d= e= f= g= h= i= j= k= l= m= n= o= p= q= r= s= t= u= v= w= x= y= z= "
# Prompt the user to choose a style
echo "Choose a style (1, 2, or 3):"
read style
# Prompt the user to enter a sentence
echo "Enter a sentence (NO capital letters):"
read sentence
# Loop through each letter in the sentence
for (( i=0; i<${#sentence}; i++ )); do
letter="${sentence:$i:1}"
# Check if the letter is a space
if [[ "$letter" == " " ]]; then
echo=" " #each space is converted to 2 spaces.
else
# Echo the letter based on the chosen style
case $style in
1)
;;
2)
;;
3)
;;
*)
echo "Invalid style"
;;
esac
fi
done
I know there are probably packages that can do similar thing, but if I can write a script for my personal use , that is better, more fun, will use my own styles and I can modify it the way I want!
I am also happy with a different approach as long as it will acheive the same result.
Last edited by meezoarch (2023-09-24 14:13:40)
Offline
Bash supports associative arrays. So you may associate each letter with the corresponding image and later reference that entry.
Sometimes I seem a bit harsh — don’t get offended too easily!
Offline
Don't loop through each character then try to replace - just us `tr` to do it all in one go:
#!/bin/sh
# styles abcdefghijklmnopqrstuvwxyz
style1='ABCDEFGHIJKLMNOPQRSTUVWXYZ' # capitalize
style2='nopqrstuvwxyzabcdefghijklm' # rot13
style3='NOPQRSTUVWXYZABCDEFGHIJKLM' # capitalize + rot13
read -p 'Choose a style (1, 2, or 3): ' nstyle
eval style=\$style$nstyle
read -p 'Enter a sentance: ' sentence
echo $sentence | tr 'a-z' $style
"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman
Offline
The problem is that my letters are ANCII art letters: for e.g. the below is letter B in one of the styles:
░█▀▄░
░█▀▄░
░▀▀░░
That is why I wanted to assign the whole thing to a variable.
Is there a way your script can be modified to achieve this?
Offline
Yes, though in a line-by-line fashion. Apply `tr` in turn for each line of the rendered text. (actually wrong, because it will not handle multiple columns)
Also note that in this particular script, under an assumption that `nstyle` variable comes from a trusted source, this is not going to be exploited; but in general this `eval` line is vulnerable to code injection. A better option is putting styles into an array and choosing the entry by index.
Last edited by mpan (2023-09-24 19:32:34)
Sometimes I seem a bit harsh — don’t get offended too easily!
Offline
◉ type greek
greek is an alias for sed 'y/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/αβcδεφγηιθκλμνοπχρστυvωξψζΑΒCΔΕΦΓΗΙΘΚΛΜΝΟΠΧΡΣΤ
VΩΞΨΖ/'
tr has a super-nasty UTF-8 pitfall…
Edit: obviously missed the last two posts…
Last edited by seth (2023-09-24 19:16:19)
Online
A note: the problem seth mentioned is important for practical uses and you certainly should be aware of it. In this script this is not going to happen, because it only works with “alphabetics from A to Z”.
For the practical uses I would rather suggest switching to a different tool altogether. I take this is for educational purposes and fun, so the value is in learning bash in general.
Sometimes I seem a bit harsh — don’t get offended too easily!
Offline
And tr will not work to replace a single character with many. But there are much bigger issues here. The art example you provided for a letter would never fit in the "style" format that you had in your initial example. If each letter can be replaced by a series of characters covering multiple character widths and heights, the much more planning / design is needed before you start trying to implement the code.
Are all the art bits going to be the same size? E.g., will each a-z character be replaced, for example, by a 5x3 character block? Or will these block sizes vary? If it varies, will it vary only between styles, or also within a style? These blocks of characters need to be placed correctly, then the cursor position reset appropriate to be ready for the next block of characters. This is not difficult, but it's also not trivial - you need to plan how you intend for this to happen.
I'd suggest progressing in order from outlining an efficient means to present the right blocks of characters, then to structuring the style data in a way that makes it both easy for a user to edit and easy for the code to use, and then finally to writing the actual code. Don't skimp on that second step. In fact, that second step is / should be the vast majority of the effort:
Fold knowledge into data, soprogram logic can be stupid and robust.
Last edited by Trilby (2023-09-24 19:28:19)
"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman
Offline
Trilby: yes, it will not work. Which is why they asked for a hint, right? And the hint has been provided, which does not have this problem.
Sometimes I seem a bit harsh — don’t get offended too easily!
Offline
Thank you very much, yes the point is the learning and the fun.
I learned a lot from your answers/comments here. I think I know what I should do now. Much appreciated.
Offline
And an example, though I suggest you first try yourself (for this reason there are some newlines at the start):
#!/usr/bin/env bash
declare -A style=(
['0a']=' AA '
['1a']='A A'
['2a']='AAAA'
['3a']='A A'
['4a']='A A'
['0b']='BBB '
['1b']='B B'
['2b']='BBB '
['3b']='B B'
['4b']='BBBB'
['0c']=' CC'
['1c']=' C '
['2c']='C '
['3c']='C '
['4c']=' CCC'
['0d']='DDD '
['1d']='D D'
['2d']='D D'
['3d']='D D'
['4d']='DDD '
)
read -p 'Enter a word:' data
for ((i=0; i<5; ++i)); do
for ((j=0; j<"${#data}"; ++j)); do
letter=${data:j:1}
echo -n " ${style[$i$letter]} "
done
echo
done
Sometimes I seem a bit harsh — don’t get offended too easily!
Offline
Here is a script I wrote a while back. Might help you.
Edit: Its not showing the characters, but the "?" is just a unicode alphabet going from A-Z. I added a ton of other alphabets from those online "Cool text generators" lol.
gothicka=(
"?"
"?"
"?"
"?"
"?"
"?"
"?"
"?"
"?"
"?"
"?"
"?"
"?"
"?"
"?"
"?"
"?"
"?"
"?"
"?"
"?"
"?"
"?"
"?"
"?"
"?"
)
tput clear
while true; do
read -rsN1 key
case "${key}" in
a) printf "%s" "${gothicka[0]}" ;;
b) printf "%s" "${gothicka[1]}" ;;
c) printf "%s" "${gothicka[2]}" ;;
d) printf "%s" "${gothicka[3]}" ;;
e) printf "%s" "${gothicka[4]}" ;;
f) printf "%s" "${gothicka[5]}" ;;
g) printf "%s" "${gothicka[6]}" ;;
h) printf "%s" "${gothicka[7]}" ;;
i) printf "%s" "${gothicka[8]}" ;;
j) printf "%s" "${gothicka[9]}" ;;
k) printf "%s" "${gothicka[10]}" ;;
l) printf "%s" "${gothicka[11]}" ;;
m) printf "%s" "${gothicka[12]}" ;;
n) printf "%s" "${gothicka[13]}" ;;
o) printf "%s" "${gothicka[14]}" ;;
p) printf "%s" "${gothicka[15]}" ;;
q) printf "%s" "${gothicka[16]}" ;;
r) printf "%s" "${gothicka[17]}" ;;
s) printf "%s" "${gothicka[18]}" ;;
t) printf "%s" "${gothicka[19]}" ;;
u) printf "%s" "${gothicka[20]}" ;;
v) printf "%s" "${gothicka[21]}" ;;
w) printf "%s" "${gothicka[22]}" ;;
x) printf "%s" "${gothicka[23]}" ;;
y) printf "%s" "${gothicka[24]}" ;;
z) printf "%s" "${gothicka[25]}" ;;
' ') printf "%s" " " ;;
$'\x0a') printf "%s\n" "" ;;
esac
done
Last edited by sweet_tea (2023-09-24 20:03:27)
Offline
wordart is a bash function
wordart ()
{
local input="${1:?[input words]}";
local height=5;
: Start position of each Alpha in the Style1 array.;
: If each Alpha has different height and width,;
: use SPACE to fill up the dimension inside Style1 array.;
declare -A alpha=(['a']='0' ['b']='5' ['c']='10');
\builtin readarray -t Style1 <<-'STY1'
__ _
/ _' |
| (_| |
\__,_|
_
| |__
| '_ \
| |_) |
|_.__/
___
/ __|
| (__
\___|
STY1
for ((j=0; j<$height; j++))
do
for ((i=0; i<${#input}; i++))
do
start=${alpha[${input:$i:1}]};
printf "%s " "${Style1[$((start + $j))]}";
done;
echo;
done;
set +x
}
Last edited by solskog (2023-10-06 03:37:44)
Offline
Pages: 1