Variable problem in script while loop - Suse

This is a discussion on Variable problem in script while loop - Suse ; I am using OpenSUSE 10.1 and puzzled by a problem with the following script (simplified version): #! /bin/bash E="Entries:" echo "T an_entry" > temp echo "U an_xref" >> temp cat temp | while read T R REST do E="${E} ${R}" ...

+ Reply to Thread
Results 1 to 5 of 5

Thread: Variable problem in script while loop

  1. Variable problem in script while loop

    I am using OpenSUSE 10.1 and puzzled by a problem with the following script
    (simplified version):

    #! /bin/bash
    E="Entries:"
    echo "T an_entry" > temp
    echo "U an_xref" >> temp
    cat temp |
    while
    read T R REST
    do
    E="${E} ${R}"
    echo "${E}"
    done
    echo "final ${E}"
    exit

    When I run it the list in the variable $E gets incremented during the loop
    but on exit from the loop it still has its original value, i.e. within the
    loop it seems to be treated as temporary. Am I doing something wrong or is
    this a bug?




  2. Re: Variable problem in script while loop

    On Sat, 15 Sep 2007 09:59:10 +0100, mjh wrote:

    > I am using OpenSUSE 10.1 and puzzled by a problem with the following
    > script (simplified version):
    >
    > #! /bin/bash
    > E="Entries:"
    > echo "T an_entry" > temp
    > echo "U an_xref" >> temp
    > cat temp |
    > while
    > read T R REST
    > do
    > E="${E} ${R}"
    > echo "${E}"
    > done
    > echo "final ${E}"
    > exit
    >
    > When I run it the list in the variable $E gets incremented during the loop
    > but on exit from the loop it still has its original value, i.e. within the
    > loop it seems to be treated as temporary. Am I doing something wrong or
    > is this a bug?


    It may well be a bug, however to work around it, form your while loop in
    this manner :-

    #!/bin/bash
    E="Entries:"
    echo "T an_entry" > temp
    echo "U an_xref" >> temp

    while read T R REST
    do
    E="${E} ${R}"
    echo "${E}"
    done < temp

    echo "final ${E}"
    exit

    JohnK

  3. Re: Variable problem in script while loop

    On Sat, 15 Sep 2007, mjh wrote:-

    >I am using OpenSUSE 10.1 and puzzled by a problem with the following script
    >(simplified version):
    >
    > #! /bin/bash
    > E="Entries:"
    > echo "T an_entry" > temp
    > echo "U an_xref" >> temp
    > cat temp |

    ^
    That's the reason for the effect you're seeing.

    > while
    > read T R REST




    >When I run it the list in the variable $E gets incremented during the loop
    >but on exit from the loop it still has its original value, i.e. within the
    >loop it seems to be treated as temporary. Am I doing something wrong or is
    >this a bug?


    It's not a bug. The reason you're seeing this is because what's
    happening when you use the '|' and pipe the temporary file into the
    start of the loop is that bash starts up a sub-shell with all the
    presently defined variables to execute the loop. Then, as the loop
    progresses, the $E of this sub-shell is changed but the other one
    doesn't. Finally, when the loop has finished, the sub-shell exits and
    all the new variables that were defined, and any changes made to already
    existing variables are lost.

    As to how to do the same thing without starting a new sub-shell, you've
    already got one answer from JohnK. Another possible one is this:

    ===== cut here =====
    #!/bin/bash

    E="Entries:"
    echo "T an_entry" > temp
    echo "U an_xref" >> temp

    E="${E}"$(cat temp | \
    while
    read T R REST
    do
    printf " %s" "${R}"
    done
    )

    echo "final ${E}"
    exit
    ===== cut here =====

    In this one, by using the $(...) structure, the "cat | while read" loop
    are executed in there own sub-shell, the printf command only prints the
    required values from each line read, prefixing it with a white space.
    Finally, all the output sent to the console (by the printf command) is
    assigned to $E.

    The end results, you get this:

    final Entries: an_entry an_xref

    which is what you were originally expecting.


    Regards,
    David Bolt

    --
    Member of Team Acorn checking nodes at 100 Mnodes/s: www.distributed.net
    RISC OS 3.11 | SUSE 10.0 32bit | SUSE 10.1 32bit | openSUSE 10.2 32bit
    RISC OS 3.6 | SUSE 10.0 64bit | SUSE 10.1 64bit | openSUSE 10.2 64bit
    TOS 4.02 | SUSE 9.3 32bit | | openSUSE 10.3b2 32bit

  4. Re: Variable problem in script while loop

    David Bolt :
    > [snip]
    > As to how to do the same thing without starting a new sub-shell, you've
    > already got one answer from JohnK. Another possible one is this:
    >
    > ===== cut here =====
    > #!/bin/bash
    >
    > E="Entries:"
    > echo "T an_entry" > temp
    > echo "U an_xref" >> temp
    >
    > E="${E}"$(cat temp | \
    > while
    > read T R REST
    > do
    > printf " %s" "${R}"
    > done
    > )
    >
    > echo "final ${E}"
    > exit
    > ===== cut here =====
    >
    > In this one, by using the $(...) structure, the "cat | while read" loop
    > are executed in there own sub-shell, the printf command only prints the
    > required values from each line read, prefixing it with a white space.
    > Finally, all the output sent to the console (by the printf command) is
    > assigned to $E.
    >
    > The end results, you get this:
    >
    > final Entries: an_entry an_xref
    >
    > which is what you were originally expecting.


    I don't think he was expecting that. Notice that only the final echo
    makes it out while the printf's are silently swallowed. I've slapped
    the original, JohnK's, and yours in the following which lets you
    select running either of the latter two, with debugging support. See
    the comments at eof:

    -------------------------------------------------
    #!/bin/bash
    #
    # Message-ID:
    # From: "mjh"
    # Newsgroups: alt.os.linux.suse
    # Subject: Variable problem in script while loop
    #

    debug=0

    if [ $debug != 0 ]; then
    set -x
    fi

    # Original from "mjh":
    #
    # E="Entries:"
    # echo "T an_entry" > temp
    # echo "U an_xref" >> temp
    # cat temp |
    # while
    # read T R REST
    # do
    # E="${E} ${R}"
    # echo "${E}"
    # done
    # echo "final ${E}"
    # exit

    # ------------------------------------------------------------
    echo
    echo -e "number 1 or 2: \c"
    read yn
    # ------------------------------------------------------------

    if [ "${yn}" = "1" ]; then
    # From: JohnK
    #

    E="Entries:"
    echo "T an_entry" > ${HOME}/tmp/temp
    echo "U an_xref" >> ${HOME}/tmp/temp

    while read T R REST ; do
    E="${E} ${R}"
    echo "${E}"
    done < ${HOME}/tmp/temp

    echo "final ${E}"

    if [ $debug = 1 ]; then
    set +x
    fi

    exit

    elif [ "${yn}" = "2" ]; then

    # ------------------------------------------------------------

    # From: David Bolt
    #
    # Doesn't really work.

    E="Entries:"
    echo "T an_entry" > ${HOME}/tmp/temp
    echo "U an_xref" >> ${HOME}/tmp/temp

    E="${E}"$(cat ${HOME}/tmp/temp | \
    while
    read T R REST
    do
    printf " %s" "${R}"
    done
    )

    # E="${E}"$($(cat ${HOME}/tmp/temp) | while read T R REST ; do printf " %s" "${R}" ; done)

    echo "final ${E}"

    if [ $debug = 1 ]; then
    set +x
    fi

    exit

    fi

    # --------------------------------------------------------------
    # Output:
    #
    # --------------------------------------------------------------
    # JohnK's:
    #
    # (0) heretic /home/keeling_ sh/temp.sh
    #
    # number 1 or 2: 1
    # Entries: an_entry
    # Entries: an_entry an_xref
    # final Entries: an_entry an_xref
    #
    # --------------------------------------------------------------
    # David Bolt's:
    #
    # (0) heretic /home/keeling_ sh/temp.sh
    #
    # number 1 or 2: 2
    # final Entries: an_entry an_xref
    #
    # There's no output from the printf's in the while loop. Enable
    # debugging:
    #
    # (0) heretic /home/keeling_ sh/temp.sh
    # + echo
    #
    # + echo -e 'number 1 or 2: \c'
    # number 1 or 2: + read yn
    # 2
    # + '[' 2 = 1 ']'
    # + '[' 2 = 2 ']'
    # + E=Entries:
    # + echo 'T an_entry'
    # + echo 'U an_xref'
    # ++ cat /home/keeling/tmp/temp
    # ++ read T R REST
    # ++ printf ' %s' an_entry
    # ++ read T R REST
    # ++ printf ' %s' an_xref
    # ++ read T R REST
    # + E='Entries: an_entry an_xref'
    # + echo 'final Entries: an_entry an_xref'
    # final Entries: an_entry an_xref
    # + '[' 1 = 1 ']'
    # + set +x
    #
    # Notice that while the printf's are executed, the output from them
    # is silently swallowed. Only the final echo makes it out.
    -------------------------------------------------

    Thanks for the interesting problem, all three of you.


    --
    Any technology distinguishable from magic is insufficiently advanced.
    (*) http://blinkynet.net/comp/uip5.html Linux Counter #80292
    - - http://www.faqs.org/rfcs/rfc1855.html Please, don't Cc: me.

  5. Re: Variable problem in script while loop


    ----- Original Message -----
    From: "mjh"
    Newsgroups: alt.os.linux.suse
    Sent: Saturday, September 15, 2007 9:59 AM
    Subject: Variable problem in script while loop


    >I am using OpenSUSE 10.1 and puzzled by a problem with the following script
    >... etc.


    Many thanks to JohnK and David Bolt, both ideas worked (of course they did!)
    but I have chosen to use the first one because I was actually collecting two
    lists: entry points and xrefs.

    Thanks again and regards Mike Hopper





+ Reply to Thread