1

I want to take integers as command line arguments into a shell script and doing basic string manipulations with these integers.

For example:

# POSIX Shell
user@host $ ./script 3 4 1 5
^
| * * *
| * * * *
| *
| * * * * *
------------

user@host $

And some pseudocode to demonstrate, how I would like to achieve this:

# Pseudocode
#!/bin/sh
for arg in $#; do
    echo $((arg * '* '))
done

# Or something similar with a loop ;-)

If someone got an idea that could lead me into the right direction in a pure POSIX Shell like /bin/sh, that would be very nice!

Luca Schulz
  • 163
  • 8
  • Only Python allows you to "multiply" strings. In other languages, you would use a loop. – that other guy Dec 06 '21 at 18:48
  • @thatotherguy Thanks for your answer! Idea, how this could be done? – Luca Schulz Dec 06 '21 at 18:49
  • See [How do I write a 'for' loop in Bash?](https://stackoverflow.com/questions/49110/how-do-i-write-a-for-loop-in-bash) to see how to repeat an action N times for some integer N – that other guy Dec 06 '21 at 18:49
  • `for arg in $#; do` will iterate exactly once, with `arg` set to the number of arguments passed to the script. You certainly meant `for arg in "$@"` (which can (and IMO should) be shortened to `for arg; do ...` – William Pursell Dec 06 '21 at 18:54
  • `yes '*' | sed ${arg}q | tr \\n \ ; echo` – William Pursell Dec 06 '21 at 18:59
  • 2
    or `yes '* ' | sed ${arg}q | tr -d \\n ; echo`, but make sure you first validate that the input is an integer. – William Pursell Dec 06 '21 at 19:00
  • `Or something similar with a loop` So write that loop. `How to parse integers as command line arguments?` All variables in shell are strings, there is nothing to parse. You can use `$( ... )` arithmetic expansion to do calculations, that's all you need. What exactly is your question? What problems did you encounter? `If someone got an idea` Write that loop, that iterates over arguments, then iterates up to the value of the argument, and prints `| ` and then prints `* `. – KamilCuk Dec 06 '21 at 19:05

3 Answers3

0

There's a lot of ways to skin this cat. Here's one:

#!/bin/bash
array=( "$@" )

function repeat() { num="${2:-100}"; printf -- "$1%.0s" $(seq 1 $num); printf '\n'; }

arraylength=${#array[@]}
for (( i=0; i<${arraylength}; i++ ));
do
   if [[ ${array[$i]} -ge $max ]]; then
        max=${array[$i]}
   fi
   printf '%s' '| '
   repeat '* ' ${array[$i]}
done

repeat '-' $(( $max+$max+3 ))

Or doing it in awk:

echo "3 4 1 5" | awk 'function a(b,c){r="";while(c-->0)r=r b;print r}{for(i=1;i<=NF;++i){printf "| ";a("* ",$i);if(m<$i)m=$i}}END{a("-",(m*2)+3)}'
JNevill
  • 46,980
  • 4
  • 38
  • 63
0

I believe this is the crux of what you're looking for, and should be scrupulously POSIXly compliant, too:

#! /bin/sh

for n; do
  printf '| ';
  i=0;
  while [ $i -lt $n ]; do
    printf '* ';
    i=$(( i + 1 ));
  done
  printf '\n';
done
pilcrow
  • 56,591
  • 13
  • 94
  • 135
  • One caveat: you need to validate the argument. This will behave oddly if `$n` is not an integer. Perhaps: `for n; do test "$n" -gt 0 2>& /dev/null || continue; ...` – William Pursell Dec 06 '21 at 22:45
0
$ cat script 
#!/bin/sh

for arg in "$@"; do
    yes | tr y '*' | head -n "$arg" | xargs
done
$ ./script 3 4 1 5
* * *
* * * *
*
* * * * *

Alternative:

$ cat script2 
#!/bin/sh

for arg in "$@"; do
    tr '\0' '*' < /dev/zero | head -c "$arg" | sed 's/./* /g'
    echo
done
$ ./script2 3 4 1 5
* * * 
* * * * 
* 
* * * * * 
root
  • 5,528
  • 1
  • 7
  • 15