0

I was trying to get the factorial of a number in bash,it's an easy program obviously ,using loop I can do this,for example

#!/usr/bin/bash
echo "Enter number"
read number
#echo  `seq -s "*" 1 $number | bc`
result=1
for((i=1;i<=number;i++))
        do
                result=$(($result*i))
        done
echo "The factorial of $number is $result"

Then I tried to find some one liners,I mean bash is famous for one liners ,using seq and bc it worked just fine.

sourav@LAPTOP-HDM6QEG8:~$ num=5
sourav@LAPTOP-HDM6QEG8:~$ seq -s "*" 1 $num | bc
120

Using $(( it also worked like it should

sourav@LAPTOP-HDM6QEG8:~$ echo $((`seq -s "*" 1 $num`))
120

However when I am trying to use expr I am not able to do it.

sourav@LAPTOP-HDM6QEG8:~$ expr `seq -s " * " 10`
expr: syntax error: unexpected argument ‘0’

I thought since * is an universal symbol may be I should escape it,but it still does not work

sourav@LAPTOP-HDM6QEG8:~$ expr `seq -s " \* " 10`
expr: syntax error: unexpected argument ‘\\*’

However I am able to perform the summation though like this

sourav@LAPTOP-HDM6QEG8:~$ expr `seq -s " + " 10`
55

So why I am getting an error when trying to get the multiplication of a series using expr,can someone explain please??

  • 3
    'expr' is a program used in ancient shell code to do math. In Posix shells like bash, use $(( expression )). In bash, ksh88+, mksh/pdksh, or zsh, you can also use '(( expression ))' or 'let expression'. – Gilles Quénot Dec 06 '22 at 20:09
  • yes ,I have heard this ,I was just curious though ,its just personal curiosity – Sourav Bhattacharya Dec 06 '22 at 20:10
  • What files are in your working directory? My guess is that you're a victim of unexpected pathname expansion, where the result of your command substitution looks like `1 * 2 * 3` and the `*` is getting replaced by a list of files in your working directory. – tjm3772 Dec 06 '22 at 20:14
  • this is the content of my current directory .. .ICEauthority .Xauthority .bash_history .bash_logout .bashrc .cache .config .dbus .gnupg .local .motd_shown .pcsc10 .profile .sudo_as_admin_successful .xorgxrdp.10.log .xsession Desktop Documents Downloads Music Pictures Public Templates Videos – Sourav Bhattacharya Dec 06 '22 at 20:18
  • 2
    The spaces around `" * "` are a syntax error. But as others have said, don't use `expr`. – tripleee Dec 06 '22 at 20:27
  • does expr works without spaces ,like expr 2*3 does not work,however expr 2 * 3 works,that is why I put spaces.without spaces it still does not work – Sourav Bhattacharya Dec 06 '22 at 20:32

1 Answers1

1

From the bash manual:

The order of expansions is: brace expansion; tilde expansion, parameter and variable expansion, arithmetic expansion, and command substitution (done in a left-to-right fashion); word splitting; and filename expansion.

Command substitution replaces the result of `command` with its output, then filename expansion replaces any globbing characters in that output with a list of filenames matching the glob. You can't get around this by embedding escape characters like \ in the data because syntax parsing happens before any expansions, so those characters will be treated as literal characters and not as escapes.

The solution to this problem is typically to use an array, because arrays can safely preserve the data:

#!/bin/bash
read -ra sequence <<< "$( seq -s " * " 10 )"
expr "${sequence[@]}"
tjm3772
  • 2,346
  • 2
  • 10