LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   shell script needs help (https://www.linuxquestions.org/questions/programming-9/shell-script-needs-help-914453/)

jack_green 11-19-2011 08:28 PM

shell script needs help
 
hello, guys. i am new to linux shell script. i have a problem about math scripting. how to write a shell script " 1x1+2x2+3x3+...+100x100= " . and can i use shift command in shell script to have this "1+3+5+7+...+99" work?

thanks for any help

Nominal Animal 11-19-2011 10:41 PM

There are many shells; which one are you using? Why would you want to use shift for this?

Shells are usually limited to integer math. For example, Bash can do
Code:

sum=0; for (( i=1; i<=100; i++ )); do sum=$((sum + i*i)) ; done ; echo $sum
and
Code:

sum=0; for (( i=1; i<=100; i+=2 )); do sum=$((sum + i)) ; done ; echo $sum
In general, it is better to use something like awk or bc to do the math instead. In this case, bc is the most suitable candidate, as it is an arbitrary-precision programmable calculator. For example, try
Code:

echo 'sum=0; for (i=1; i<=100; i++) sum += i*i; print sum, "\n"' | bc
and
Code:

echo 'sum=0; for (i=1; i<=100; i+=2) sum += i; print sum, "\n"' | bc
See man 1 bc for details.

jack_green 11-19-2011 10:52 PM

Quote:

Originally Posted by Nominal Animal (Post 4528682)
There are many shells; which one are you using? Why would you want to use shift for this?

Shells are usually limited to integer math. For example, Bash can do
Code:

sum=0; for (( i=1; i<=100; i++ )); do sum=$((sum + i*i)) ; done ; echo $sum
and
Code:

sum=0; for (( i=1; i<=100; i+=2 )); do sum=$((sum + i)) ; done ; echo $sum
In general, it is better to use something like awk or bc to do the math instead. In this case, bc is the most suitable candidate, as it is an arbitrary-precision programmable calculator. For example, try
Code:

echo 'sum=0; for (i=1; i<=100; i++) sum += i*i; print sum, "\n"' | bc
and
Code:

echo 'sum=0; for (i=1; i<=100; i+=2) sum += i; print sum, "\n"' | bc
See man 1 bc for details.



thanks so much. i use bash shell as my default shell. i just wanna know more about linux shell scripts. but you did not answer my second question : could i use shift command on this test ?

Nominal Animal 11-19-2011 11:59 PM

Yes, there is a way you can calculate the sums in a way that utilizes the shift built-in. It involves a function (or a separate script if the shell does not support functions -- Bash does), which sums its arguments (or squares of its arguments), and echoes the results.

shift is useful in looping over all arguments in a while loop, although one could use a for loop over the arguments as well.

To get the result, you would need to call the function with all summands as arguments, but the seq utility is useful for that.

The solution using shift is almost a dozen lines of Bash. I cannot imagine why you would want to do it that way -- unless this is homework.

Is this homework?

jack_green 11-20-2011 12:26 AM

Quote:

Originally Posted by Nominal Animal (Post 4528710)
Yes, there is a way you can calculate the sums in a way that utilizes the shift built-in. It involves a function (or a separate script if the shell does not support functions -- Bash does), which sums its arguments (or squares of its arguments), and echoes the results.

shift is useful in looping over all arguments in a while loop, although one could use a for loop over the arguments as well.

To get the result, you would need to call the function with all summands as arguments, but the seq utility is useful for that.

The solution using shift is almost a dozen lines of Bash. I cannot imagine why you would want to do it that way -- unless this is homework.

Is this homework?


sorry, it's not my homework . i just happened to heard that shift can use for looping , but i don't understand how to use it.
it said that VAR=1,VAR=2,VAR=3... after "shift", it should be VAR1=2,VAR2=3..... but how to use the position parameter for looping . i am a totally shell script beginner.

Nominal Animal 11-20-2011 01:23 AM

Consider this Bash code:
Code:

sumargs () {
    local sum=0
    while [ $# -gt 0 ]; do
        sum=$(( sum + $1 ))
        shift 1
    done
    echo $sum
}

sqrargs () {
    local sum=0
    while [ $# -gt 0 ]; do
        sum=$(( sum + $1 * $1 ))
        shift 1
    done
    echo $sum
}

sqrargs $(seq 1 100)

sumargs $(seq 1 2 100)

$# evaluates the number of positional parameters -- command-line parameters to a script, or parameters if in a function. First one is $1, second $2 and so on. shift N will discard the first N parameters, and rename the leftovers starting from one ($1). It only works for positional parameters, not for variables in general.

The while loops above can be read as "as long as there are more than zero positional parameters, do ..., then discard the first positional parameter shifting the rest one place down." This results in $1 cycling through each parameter given to the function.

seq first last would output each integer number from first to last, inclusive.
seq first step last outputs first , first+step , first+step+step , and so on, up to and including last.

The $(...) is equivalent to backticks, and evaluates to the output of ... . Thus, the output from the seq is given to the function as positional parameters.

While Bash functions can return a number, it is limited to a very small range, usually between 0 and 255, inclusive, with 0 meaning success/true, and all others failure/false. (Nonzero values always indicate an error code, although the meaning of each code tends to be program-specific. There are lists and conventions, but nothing universal.)

Therefore the function really needs to output the result. I used echo. If I wanted to format the output, I'd use for example printf '%d\n' $sum instead.

David the H. 11-20-2011 08:08 AM

To provide (hopefully) a clear and simple explanation:

Every command you enter consists of the command-name and zero or more arguments following it.

In shell scripting, the name of the command itself is stored in the special parameter $0, and the arguments following it in $1, $2, $3, etc.

The shift built-in command simply moves the contents of the parameters down the list. When executed, the contents of $1 are deleted and $2 moves over to become $1, $3 becomes $2, etc. ($0 remains unaffected). A number can also optionally be given so that it shifts multiple steps at once.

So depending on what you want to do, it is possible to use shift as a kind of looping device, but it's far from the most usual option, as it's both limited and destructive to your data. Your shell provides much better ways to iterate through multiple inputs.

Here are a few useful bash scripting references for you to study. I particularly recommend the first as a good introduction into the basics:

http://mywiki.wooledge.org/BashGuide
http://www.linuxcommand.org/index.php
http://mywiki.wooledge.org/BashFAQ
http://mywiki.wooledge.org/BashPitfalls
http://tldp.org/LDP/Bash-Beginners-G...tml/index.html
http://www.tldp.org/LDP/abs/html/index.html
http://www.gnu.org/software/bash/manual/bashref.html
http://wiki.bash-hackers.org/start

jack_green 11-20-2011 06:36 PM

Quote:

Originally Posted by Nominal Animal (Post 4528735)
Consider this Bash code:
Code:

sumargs () {
    local sum=0
    while [ $# -gt 0 ]; do
        sum=$(( sum + $1 ))
        shift 1
    done
    echo $sum
}

sqrargs () {
    local sum=0
    while [ $# -gt 0 ]; do
        sum=$(( sum + $1 * $1 ))
        shift 1
    done
    echo $sum
}

sqrargs $(seq 1 100)

sumargs $(seq 1 2 100)

$# evaluates the number of positional parameters -- command-line parameters to a script, or parameters if in a function. First one is $1, second $2 and so on. shift N will discard the first N parameters, and rename the leftovers starting from one ($1). It only works for positional parameters, not for variables in general.

The while loops above can be read as "as long as there are more than zero positional parameters, do ..., then discard the first positional parameter shifting the rest one place down." This results in $1 cycling through each parameter given to the function.

seq first last would output each integer number from first to last, inclusive.
seq first step last outputs first , first+step , first+step+step , and so on, up to and including last.

The $(...) is equivalent to backticks, and evaluates to the output of ... . Thus, the output from the seq is given to the function as positional parameters.

While Bash functions can return a number, it is limited to a very small range, usually between 0 and 255, inclusive, with 0 meaning success/true, and all others failure/false. (Nonzero values always indicate an error code, although the meaning of each code tends to be program-specific. There are lists and conventions, but nothing universal.)

Therefore the function really needs to output the result. I used echo. If I wanted to format the output, I'd use for example printf '%d\n' $sum instead.



thanks so much.


All times are GMT -5. The time now is 04:48 PM.