Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I shift digits in bash?

Tags:

bash

I have a homework assignment that is asking to shift a decimal number by a specified amount of digits. More clearly this bash script will take two input arguments, the first is the number(maximum 9 digits) that the shift will be performed on and the second is the number(-9 to 9) of digits to shift. Another requirement is that when a digit is shifted off the end, it should be attached to the other end of the number. One headache of a requirement is that we cannot use control statements of any kind: no loops, no if, and switch cases.

Example: 12345 3 should come out to 345000012 and 12345 -3 should be 12345000

I know that if I mod 12345 by 10^3 I get 345 and then if I divide 12345 by 10^3 I get 12 and then I can just concatenate those two variables together to get 34512. I am not quite sure if that is exactly correct but that is the closest I can get as of now. As far as the -3 shift, I know that 10^-3 is .001 and would work however when I try using 10^-3 in bash I get an error.

I am just lost at this point, any tips would be greatly appreciated.

EDIT: After several hours of bashing (pun intended) my head against this problem, I finally came up with a script that for the most part works. I would post the code right now but I fear another student hopelessly lost might stumble upon it. I will check back and post what I came up with in a week or two. I was able to do it with mods and division. Thank you all for the responses, it really helped me to open up and think about the problem from different angles.

like image 857
mfunaro Avatar asked Jan 10 '11 20:01

mfunaro


People also ask

What is $# in bash?

$# is a special variable in bash , that expands to the number of arguments (positional parameters) i.e. $1, $2 ... passed to the script in question or the shell in case of argument directly passed to the shell e.g. in bash -c '...' .... .

What is bash shift command?

The shift command is one of the Bourne shell built-ins that comes with Bash. This command takes one argument, a number. The positional parameters are shifted to the left by this number, N. The positional parameters from N+1 to $# are renamed to variable names from $1 to $# - N+1.

What is Shift 2 in shell script?

shift is a bash built-in which kind of removes arguments from the beginning of the argument list. Given that the 3 arguments provided to the script are available in $1 , $2 , $3 , then a call to shift will make $2 the new $1 . A shift 2 will shift by two making new $1 the old $3 .


1 Answers

Here's a hint:

echo ${string:0:3}
echo ${#string}

Edit (2011-02-11):

Here's my solution. I added some additional parameters with defaults.

rotate-string ()
{
    local s=${1:-1} p=${2:--1} w=${3:-8} c=${4:-0} r l
    printf -vr '%0*d' $w 0    # save $w zeros in $r
    r=${r//0/$c}$s            # change the zeros to the character in $c, append the string
    r=${r: -w}                # save the last $w characters of $r
    l=${r: -p%w}              # get the last part of $r ($p mod %w characters)
    echo "$l${r::w-${#l}}"    # output the Last part on the Left and the Right part which starts at the beginning and goes for ($w minus the_length_of_the_Left_part) characters
}

usage: rotate-string string positions-to-rotate width fill-character

example: rotate-string abc -4 9 =

result: ==abc====

Arguments can be omitted starting from the end and these defaults will be used:

  • fill-character: "0"
  • width: 8
  • positions-to-rotate: -1
  • string: "1"

More examples:

$ rotate-string
00000010
$ rotate-string 123 4
01230000

Fun stuff:

$ for i in {126..6}; do printf '%s\r' "$(rotate-string Dennis $i 20 .)"; sleep .05; done; printf '\n'

$ while true; do for i in {10..1} {1..10}; do printf '%s\r' "$(rotate-string : $i 10 .)"; sleep .1; done; done

$ while true; do for i in {40..2} {2..40}; do printf '%s\r' "$(rotate-string '/\' $i 40 '_')"; sleep .02; done; done

$ d=0; while true; do for i in {1..10} {10..1}; do printf '%s\r' "$(rotate-string $d $i 10 '_')"; sleep .02; done; ((d=++d%10)); done

$ d=0; while true; do for i in {1..10}; do printf '%s\r' "$(rotate-string $d $i 10 '_')"; sleep .2; ((d=++d%10)); done; done

$ shape='▁▂▃▄▅▆▇█▇▆▅▄▃▂▁'; while true; do for ((i=1; i<=COLUMNS; i++)); do printf '%s\r' "$(rotate-string "$shape" $i $COLUMNS ' ')"; done; done
like image 173
Dennis Williamson Avatar answered Sep 20 '22 16:09

Dennis Williamson