0

I wrote a script that reads a Plain text and a key, and then loops trough each character of plain text and shifts it with the value of the corresponding character in key text, with a=0 b=1 c=2 ... z = 25

the code works fine but with a string of size 1K characters it takes almost 3s to execute.

this is the code:

    small="abcdefghijklmnopqrstuvwxyz" ## used to search and return the position of some small letter in a string
    capital="ABCDEFGHIJKLMNOPQRSTUVWXYZ" ## used to search and return the position of some capital letter in a string

    read Plain_text
    read Key_text
    ## saving the length of each string
    length_1=${#Plain_text}
    length_2=${#Key_text}
    printf " Your Plain text is: %s\n The Key is: %s\n The resulting Cipher text is: " "$Plain_text" "$Key_text"

        for(( i=0,j=0;i<$length_1;++i,j=`expr $(($j + 1)) % $length_2` )) ## variable 'i' is the index for the first string, 'j' is the index of the second string
        do
            ## return a substring statring from position 'i' and with length 1
            c=${Plain_text:$i:1}
            d=${Key_text:$j:1}  

            ## function index takes two parameters, the string to seach in and a substring,
            ## and return the index of the first occerunce of the substring with base-insex 1

            x=`expr index "$small" $c` 
            y=`expr index "$small" $d`

            ##shifting the current letter to the right with the vaule of the corresponding letter in the key mod 26
            z=`expr $(($x + $y - 2)) % 26`

            ##print the resulting letter from capital letter string
            printf "%s" "${capital:$z:1}"
        done
    echo ""

How is it possible to improve the performance of this code. Thank you.

4
  • 3
    Don't use expr, use Bash's arithmetic. In general, expr should not be used in Bash. Never. It's very bad. This will already save you a lot of subshells. We can't execute your code as we're missing some data. Post your full script. Commented Mar 7, 2015 at 14:43
  • 1
    Better than "your full script" would be "a subset of your script that has been actually tested to work, with no external dependencies" (note that requiring the reader to produce test data is a dependency). Otherwise, the code given here fails the "correct" part of MCVE. Commented Mar 7, 2015 at 15:31
  • I added the missing variables for the code, now you can use it. thank you for the good point, I never thought of that before :D Commented Mar 7, 2015 at 16:19
  • cab you please tell me how to use the function " index "$small" $c " with arithmetic expressions, I keep getting this error ./t: line 22: index "abcdefghijklmnopqrstuvwxyz" "h" : syntax error: invalid arithmetic operator (error token is ""abcdefghijklmnopqrstuvwxyz" "h" ") when using this command: x=$((index "$small" "$c" )) Commented Mar 7, 2015 at 16:37

3 Answers 3

1

You are creating 4 new processes in each iteration of your for loop by using command substitution (3 substitutions in the body, 1 in the head). You should use arithmetic expansion instead of calling expr (search for $(( in the bash(1) manpage). Note that you don't need the $ to substitute variables inside $(( and )).

Sign up to request clarification or add additional context in comments.

Comments

0

you can change character like this

a=( soheil )
echo ${a/${a:0:1}/${a:1:1}} 

for change all char use loop like for and for change char to upper

echo soheil | tr "[:lower:]" "[:upper:]"

i hope i understand your question. be at peace

Comments

0

You will have a lot of repeating chars in a 1K string.
Imagine the input was 1M.

You should calculate all request/respond pairs in front, so your routine only has to lookup the replacement.
I would think of a solution with arrays is the best approach here.

1 Comment

well that would make a difference if each character from a to z is shifted by fixed amount, but in my code, every letter will be shifted by the corresponding character from the second string. If you mean to use your idea instead of taking substrings out of "small" "capital" strings, this is a good idea. :D

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.