• Home   /  
  • Archive by category "1"

With Expected At Least One Variable Assignment In Bash

You asked for answers to two questions:

  1. You asked for an explanation of why your current code does not produce the expected output.

  2. You asked for the correct way to write your code so that it does produce the expected output.

Looking at your code, I can see two likely explanations for why you wrote your code the way you did:

  1. There might be some slight confusion about the syntax of a for-loop.

  2. There might be some slight confusion about the order of evaluation in what's called a simple command.

for-loop syntax

In the first case, I would say that you're missing a semicolon after your variable assignment. If you want to write your for-loop on a single line then you need to put a semi-colon after each command in the loop body. Try this instead:

Another alternative would be to write the for-loop using the multi-line syntax with newlines in place of the semicolons:

You can also mix-and-match semicolons and newlines, e.g.:

evaluation of simple commands

In the second case, I would say that you probably had assumed that the variable assignment in the prologue of the command (i.e. the assignment) occurs before the variable expansion in the body of the command (i.e. the expansion of in ). But this is actually not the case. To verify this we can refer to the page on simple command expansion in the Bash Manual or to the subsection on simple commands in the Posix Specification. Both of these references include the following passage:

A "simple command" is a sequence of optional variable assignments and redirections, in any sequence, optionally followed by words and redirections, terminated by a control operator.

When a given simple command is required to be executed (that is, when any conditional construct such as an AND-OR list or a case statement has not bypassed the simple command), the following expansions, assignments, and redirections shall all be performed from the beginning of the command text to the end:

  1. The words that are recognized as variable assignments or redirections according to Shell Grammar Rules are saved for processing in steps 3 and 4.

  2. The words that are not variable assignments or redirections shall be expanded. If any fields remain following their expansion, the first field shall be considered the command name and remaining fields are the arguments for the command.

  3. Redirections shall be performed as described in Redirection.

  4. Each variable assignment shall be expanded for tilde expansion, parameter expansion, command substitution, arithmetic expansion, and quote removal prior to assigning the value.

Notice that step 2 is where the variable expansion in the command occurs, but step 1 tells us that the variable assignments are saved until steps 3 and 4. It follows that the expression is expanded to before the assignment takes place. This explains why you were getting empty output.

For further discussion on this topic see the following posts:

  • Two popular shells: tcsh and bash
  • there are many different shells available, but others tend to be very similar to one or both of these Most of the commands that we use are common.
  • Check your shell type:
  • Change Shell:
  • you can always type the name of the shell to switch.(bash,csh,sh,tcsh)

    If you want to change permantly, (change your login shell), you can do this:

    or (chsh -s bash)
  • Some nice feature of modern shells:
  • command line editing file name completion (Tab key)
  • startup file:
  • How to define User defined variables (UDV)

  • To define UDV use following syntax
    Syntax:
    variable name=value

    'value' is assigned to given 'variable name' and Value must be on right side = sign.

    Example:
    # this is ok
    # Error, NOT Ok, Value must be on right side of = sign.
    To define variable called 'vech' having value Bus

    To define variable called n having value 10

    Tips:
    1. Don't put spaces on either side of the equal sign when assigning value to variable.
    2. For e.g. In following variable declaration there will be no error

      But there will be problem for any of the following variable declaration:
    3. Variables are case-sensitive, just like filename in Linux.
    4. You can define NULL variable as follows (NULL variable is variable which has no value at the time of definition)
    5. For e.g.
      $ vech=
      $ vech=""
      Try to print it's value by issuing following command

      Nothing will be shown because variable has no value i.e. NULL variable.
    6. Do not use ?,* etc, to name your variable names.
    7. Use set name=value in tcsh Shell.
  • How to print or access value of UDV (User defined variables)

  • To print or access UDV use following syntax
    Syntax:
    $variablename

    Define variable vech and n as follows:

    To print contains of variable 'vech' type

    It will print 'Bus',To print contains of variable 'n' type command as follows

    Caution: Do not try $ echo vech, as it will print vech instead its value 'Bus' and $ echo n, as it will print n instead its value '10', You must use $ followed by variable name.

  • Echo and Quotes

  • There are three types of quotes

    Quotes

    Name

    Meaning

    "Double Quotes"Double Quotes" - Anything enclose in double quotes removed meaning of that characters (except \ and $).
    'Single quotes'Single quotes' - Enclosed in single quotes remains unchanged.
    `Back quote
    `Back quote` - To execute command

    Example:
    $ echo "Today is date"
    Can't print message with today's date.
    $ echo "Today is `date`".
    It will print today's date as, Today is Tue Jan ....,Can you see that the `date` statement uses back quote?

  • Shell Arithmetic

  • Use to perform arithmetic operations.

    Syntax:
    expr op1 math-operator op2

    Examples:

    Note:
    expr 20 %3 - Remainder read as 20 mod 3 and remainder is 2.
    expr 10 \* 3 - Multiplication use \* and not * since its wild card.

    For the last statement not the following points

    (1) First, before expr keyword we used ` (back quote) sign not the (single quote i.e. ') sign. Back quote is generally found on the key under tilde (~) on PC keyboard OR to the above of TAB key.

    (2) Second, expr is also end with ` i.e. back quote.

    (3) Here expr 6 + 3 is evaluated to 9, then echo command prints 9 as sum

    (4) Here if you use double quote or single quote, it will NOT work
    For e.g.
    $ echo "expr 6 + 3" # It will print expr 6 + 3
    $ echo 'expr 6 + 3' # It will print expr 6 + 3

  • The read Statement

  • Use to get input (data from user) from keyboard and store (data) to variable.
    Syntax:
    read variable1, variable2,...variableN

    Following script first ask user, name and then waits to enter name from the user via keyboard. Then user enters name from keyboard (after giving name you have to press ENTER key) and entered name through keyboard is stored (assigned) to variable fname.

    Run it as follows:

    Your first name please: world
    Hello world, Lets be friend!

  • if and test command or [ expr ]

  • test command or [ expr ] is used to see if an expression is true, and if it is true it return zero(0), otherwise returns nonzero for false.
    Syntax:
    test expression OR [ expression ]

    Example:
    Following script determine whether given argument number is positive.

    Run it as follows
    $ chmod 755 ispostive

    $ ispostive 5
    5 number is positive

    $ispostive -45
    Nothing is printed

    $ispostive
    ./ispostive: test: -gt: unary operator expected

    Detailed explanation
    The line, if test $1 -gt 0 , test to see if first command line argument($1) is greater than 0. If it is true(0) then test will return 0 and output will printed as 5 number is positive but for -45 argument there is no output because our condition is not true(0) (no -45 is not greater than 0) hence echo statement is skipped. And for last statement we have not supplied any argument hence error ./ispostive: test: -gt: unary operator expected, is generated by shell , to avoid such error we can test whether command line argument is supplied or not.

    test or [ expr ] works with
    1.Integer ( Number without decimal point)
    2.File types
    3.Character strings

    For Mathematics, use following operator in Shell Script

    Mathematical Operator in  Shell Script MeaningNormal Arithmetical/ Mathematical StatementsBut in Shell
       For test statement with if commandFor [ expr ] statement with if command
    -eqis equal to5 == 6if test 5 -eq 6if [ 5 -eq 6 ]
    -ne is not equal to5 != 6if test 5 -ne 6if [ 5 -ne 6 ]
    -lt is less than5 < 6if test 5 -lt 6if [ 5 -lt 6 ]
    -le is less than or equal to5 <= 6if test 5 -le 6if [ 5 -le 6 ]
    -gt is greater than5 > 6if test 5 -gt 6if [ 5 -gt 6 ]
    -ge is greater than or equal to5 >= 6if test 5 -ge 6if [ 5 -ge 6 ]

    NOTE: == is equal, != is not equal.

    For string Comparisons use

    OperatorMeaning
    string1 = string2string1 is equal to string2
    string1 != string2 string1 is NOT equal to string2
    string1 string1 is NOT NULL or not defined 
    -n string1 string1 is NOT NULL and does exist
    -z string1 string1 is NULL and does exist

    Shell also test for file and directory types

    TestMeaning
    -s file   Non empty file
    -f file   Is File exist or normal file and not a directory 
    -d dir    Is Directory exist and not a file
    -w file   Is writeable file
    -r file    Is read-only file
    -x file   Is file is executable

    Logical Operators

    Logical operators are used to combine two or more condition at a time

    Operator           Meaning
    ! expression Logical NOT
    expression1  -a  expression2 Logical AND
    expression1  -o  expression2 Logical OR

  • if...else...fi

  • If given condition is true then command1 is executed otherwise command2 is executed.
    Syntax:
    if condition then condition is zero (true - 0) execute all commands up to else statement else if condition is not true then execute all commands up to fi fi

    For e.g. Write Script as follows:


    Try it as follows:
    $ chmod 755 isnump_n

    $ isnump_n 5

    5 number is positive

    $ isnump_n -45

    -45 number is negative

    $ isnump_n

    ./ispos_n : You must give/supply one integers

    $ isnump_n 0

    0 number is negative

    Detailed explanation
    First script checks whether command line argument is given or not, if not given then it print error message as "./ispos_n : You must give/supply one integers". if statement checks whether number of argument ($#) passed to script is not equal (-eq) to 0, if we passed any argument to script then this if statement is false and if no command line argument is given then this if statement is true. The echo command i.e.
    echo "$0 : You must give/supply one integers"
             |              |
             |              |
            1             2
    1 will print Name of script
    2 will print this error message
    And finally statement exit 1 causes normal program termination with exit status 1 (nonzero means script is not successfully run).

    The last sample run $ isnump_n 0 , gives output as "0 number is negative", because given argument is not > 0, hence condition is false and it's taken as negative number. To avoid this replace second if statement with if test $1 -ge 0.

  • Multilevel if-then-else

  • Syntax:
    if condition then condition is zero (true - 0) execute all commands up to elif statement elif condition1
    then condition1 is zero (true - 0) execute all commands up to elif statement elif condition2 then condition2 is zero (true - 0) execute all commands up to elif statement else None of the above condtion,condtion1,condtion2 are true (i.e. all of the above nonzero or false) execute all commands up to fi fi
  • for Loop

  • Syntax:
    for { variable name } in { list } do execute one for each item in the list until the list is not finished (And repeat all statement between do and done) done

    Even you can use following syntax:

    Syntax:

    for (( expr1; expr2; expr3 ))
    do
    ..... ... repeat all statements between do and done until expr2 is TRUE Done

    In above syntax BEFORE the first iteration, expr1 is evaluated. This is usually used to initialize variables for the loop. 
    All the statements between do and done is executed repeatedly UNTIL the value of expr2 is TRUE.
    AFTER each iteration of the loop, expr3 is evaluated. This is usually use to increment a loop counter.

    Run it above script as follows:
    $ chmod +x testfor
    $ ./testfor

    $ cat > for2
    for ((  i = 0 ;  i <= 5;  i++  ))
    do
      echo "Welcome $i times"
    done

    Run the above script as follows:
    $ chmod +x for2
    $ ./for2

    Welcome 0 times
    Welcome 1 times
    Welcome 2 times
    Welcome 3 times
    Welcome 4 times
    Welcome 5 times

    In above example, first expression (i = 0), is used to set the value variable i to zero.
    Second expression is condition i.e. all statements between do and done executed as long as expression 2 (i.e continue as long as the value of variable i is less than or equel to 5) is TRUE.
    Last expression i++ increments the value of i by 1 i.e. it's equivalent to i = i + 1 statement.

  • while loop

  • Syntax: while [ condition ] do command1 command2 command3 .. .... done

    Loop is executed as long as given condition is true. For e.g.:

    Save it and try as
    $ chmod 755 nt1
    $./nt1 7

  • The case Statement

  • The case statement is good alternative to Multilevel if-then-else-fi statement. It enable you to match several values against one variable. Its easier to read and write.
    Syntax:
    case $variable-name in pattern1) command ... .. command;; pattern2) command ... .. command;; patternN) command ... .. command;; *) command ... .. command;; esac

    The $variable-name is compared against the patterns until a match is found. The shell then executes all the statements up to the two semicolons that are next to each other. The default is *) and its executed if no match is found. For e.g. write script as follows:

    Save it by pressing CTRL+Dand run it as follows:
    $ chmod +x car
    $ car van
    $ car car
    $ car Maruti-800

    One thought on “With Expected At Least One Variable Assignment In Bash

    Leave a comment

    L'indirizzo email non verrĂ  pubblicato. I campi obbligatori sono contrassegnati *