LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Simple read line_ function hangs indefinitely (https://www.linuxquestions.org/questions/programming-9/simple-read-line_-function-hangs-indefinitely-4175583970/)

andrew.comly 07-07-2016 03:07 AM

Simple read line_ function hangs indefinitely
 
I would like to use the function read line{line number here} in linux bash programming language. Unfortunately, today that function does not work. I would like to read commented out lines 6-10. My attempt below:
Code:

#!/bin/bash
#mysystem="Linux a-NC210-NC110 3.13.0-85-generic #129-Ubuntu SMP Thu Mar 17 20:50:41 UTC 2016 i686 i686 i686 GNU/Linux"

#Student="Andrew Comly"                                Teacher: Mendell Cooper

# Normal
# as
# the
# next
# guy.

        read -r line6       
        echo $line6
       
        read line7       
        echo $line7

        read line8
        echo $line8

        read -r line9
        echo $line9

        read line10
        echo $line10
       
  #Wow, this is really verbose!!

The result is that the terminal just hangs indefinitely. Both read -r and read don't work.


What am I doing wrong?

grail 07-07-2016 04:36 AM

Ok, so first off, use / and not \ in the closing code tag to make them work :)

As for your example, you do realise that the read command will wait until you enter something before moving to the next line of the script?

So we can ignore all but the first read:
Code:

read -r line6
After this line in the code your terminal will wait for you to enter for the read command to read :) Only once the enter key has been hit (or maybe ctrl-d too) will you get the next line of code executed

andrew.comly 07-08-2016 03:31 AM

questions formated to 'human readable' form important
 
Quote:

Originally Posted by grail (Post 5571710)
Ok, so first off, use / and not \ in the closing code tag to make them work :)

Thanks, Pardon me.

sundialsvcs 07-08-2016 07:37 AM

Yes, and since this is a homework assignment, get your teacher involved and keep him there. That's what he's there for.

Probably the most important skill in programming is to learn how to see what a program is (not) doing, and to devise a way to figure it out. You can short-change yourself of that if you simply throw your hands up, post out to a forum, and ask someone else to give you the answer. A much better strategy would be to ask Mr. Cooper to give you a nudge in the right direction. Don't have any reluctance to do that!

andrew.comly 07-08-2016 06:48 PM

something strange going on
 
Quote:

Originally Posted by grail (Post 5571710)
As for your example, you do realise that the read command will wait until you enter something before moving to the next line of the script?

So we can ignore all but the first read:
Code:

read -r line6
After this line in the code your terminal will wait for you to enter for the read command to read :) Only once the enter key has been hit (or maybe ctrl-d too) will you get the next line of code executed

Even though I have used "read -r Var" and "read Var" before, I was under the impression that the "line" in "read line#" & "read -r line#" was an dashless option, which would do something along the lines that "$0" would do, almost like a preset variable.

I gained this false notion from when Example 15-4. What happens when read has no variable uses the code block:
Code:

{ # Code block.
read                                # Line 1, to be discarded.
read line2                        # Line 2, saved in variable.

} <$0
echo "Line 2 of this script is:"
echo "$line2"
echo

and the second line of the script is "# read-novar.sh", which is echoed.

Looking at this practice exercise I still really think something special exists about "line2", more specifically the line "read line2" above. If you look at this entire program you will see that the variable "line2" was never set.

andrew.comly 07-08-2016 07:54 PM

Actually I have no teacher
 
Quote:

Originally Posted by sundialsvcs (Post 5572468)
Yes, and since this is a homework assignment, get your teacher involved and keep him there. That's what he's there for.
...
A much better strategy would be to ask Mr. Cooper to give you a nudge in the right direction. Don't have any reluctance to do that!

This could be a misunderstanding, but when I wrote
Code:

#Student="Andrew Comly"                                Teacher: Mendell Cooper
what I meant by "Teacher: Mendell Cooper" I meant that the author of the book I was reading and learning shellscripting from is Mendell Cooper. I'll probably never get a chance to meet Mendell Cooper, but certainly his eBook Advanced Bash Scripting is the most useful thing I have used/discovered so far. Not everybody has a non-poverty income thus we can only use open source materials/resources online to learn. However even though I can't pay/donate $ to Mendel Cooper now, I can pay my respects/thanks.

___________________________________

Quote:

Originally Posted by sundialsvcs (Post 5572468)
Probably the most important skill in programming is to learn how to see what a program is (not) doing, and to devise a way to figure it out. You can short-change yourself of that if you simply throw your hands up, post out to a forum, and ask someone else to give you the answer.

Actually I did give significant effort to try to solve this problem on my own, more than just the three attempts that were "presentable". I simply just don't know why
Code:

{ # Code block.
read                                # Line 1, to be discarded.
read line2                        # Line 2, saved in variable.

} <$0

works the way it does exactly how it is written but then when you replace the "read line2" with another number, e.g.
Code:

{ # Code block.
        read line1                        # Line 1, to be discarded.
        echo
        read line6
        echo "$line6"
} <$0

echo "Line 6 of this script is:"
echo "$line6"

Still this will echo "line 2"??!

grail 07-08-2016 07:54 PM

In the example it is set by reading from the input of $0 and seeing that $0 refers to the script itself it is now reading lines from itself. I can assure you that those variables could have just as easily been
foo and bar and bar would contain the same data as line2. Of course you can try this and also change the digit to be say line10 but you will still only get the second line of the file.

andrew.comly 07-08-2016 11:51 PM

Solution
 
I GOT IT!!!!!
If you want the code block to read line "N" of the script $0, than the "read" command must be executed "N-1" times before line "N" is read. E.g.
Code:

{ # Code block.       
  #SET LINE NUMBER TO BE DISPLAYED
    TgtLineNum=5                # This is the target line number to display
    read; read; read; read;        # Lines 1-4 to be discarded.
  #DISPLAY CHOICE LINE
    read targetLine
} <$0                                # Line 5, saved in variable.

echo "Line $TgtLineNum of this script is:"
echo "$targetLine"

Too bad read doesn't have a number option, but that's besides the point.

Now I understand how to echo the choice line of the script $0.

Thanks a-lot grail!!

andrew.comly 07-09-2016 06:34 AM

Original example program correction
 
Correction of original program below:
Code:

#!/bin/bash
#mysystem="Linux a-NC210-NC110 3.13.0-85-generic #129-Ubuntu SMP Thu Mar 17 20:50:41 UTC 2016 i686 i686 i686 GNU/Linux"


# Normal
# as
# the
# next
# guy.

{
  #SET LINE NUMBER TO BE DISPLAYED
    #VARIABLES
      #DEFINE       
        #EXCLUDE LINES BEFORE TARGET LINES
          read; read; read; read;
        #READ CHOICE LINES
          read line1;
          read line2;
          read line3;
          read line4;
          read line5;
} <$0
       
  #DISPLAY CHOICE LINE
    echo "${line1#* }${line2#*#}${line3#*#}${line4#*#}${line5#*#}"

Where I finally got the desired results:
Code:

$./Ch15_IntCmd_04ReadLine.sh
Normal as the next guy.


grail 07-09-2016 11:19 AM

Alternative:
Code:

#!/usr/bin/env bash
#mysystem="Linux a-NC210-NC110 3.13.0-85-generic #129-Ubuntu SMP Thu Mar 17 20:50:41 UTC 2016 i686 i686 i686 GNU/Linux"


# Normal
# as
# the
# next
# guy.

{
  for i in {1..9}
  do 
    (( i < 5 )) && read || read _ word
    [[ "$out" ]] && out="$out $word" || out=$word
  done

} <$0

#DISPLAY CHOICE LINE
echo "$out"


andrew.comly 07-10-2016 09:11 PM

PEDAGOGICAL SYNOPSIS for grail's alternative method
 
Quote:

Originally Posted by grail (Post 5573123)
Alternative:
Code:

#!/usr/bin/env bash
...
    (( i < 5 )) && read || read _ word
    [[ "$out" ]] && out="$out $word" || out=$word


______________________ PEDAGOGICAL ANALYSIS 01 _________________________
At first I did not understand
Code:

read _ word
Even though i could not find this technique on the web, I pondered and hacked around with it, then I realized that this is a way to read a line not starting with the first word. More specifically:

Read a line starting with the Nth word
syntax: $ read _(write " _" N times) word(N+1)

Examples
1) Read a line skipping the first 5 words.
Code:

$ read _ _ _ _ _ word2   
> Tigers Tail Orchid is not an orchid.
$ echo $word2

an orchid.

2) Read first 4 words of a line, skip 5th word and then read rest of sentence.
Code:

$ read word1 word2 word3 word4 _ phrase
> In Washington lobbying is not a crime.
$ echo $word{3,4} $phrase

lobbying is a crime.

_______________________ PEDAGOGICAL ANALYSIS 02 ________________________
Then I did not quite get
Code:

(( i < 5 )) && read || read _ word
I returned to the Advanced Bash scripting textbook, and I reviewed the chapter on tests, which led me to realize that:
Code:

(( i < 5 )) && read || read _ word
==                                # is equivalent to
(( condition1 )) && command1 || commandA

and thus
Code:

(( condition1 )) && command1 || commandA
==
{
if (( condition1 )); then
        command1
else
        commandA
fi
}

_____________________ PEDAGOGICAL ANALYSIS 03 __________________________

Finally I also had some problems with
Code:

[[ "$out" ]] && out="$out $word" || out=$word
With the above principles covered we can immediately see the
Code:

(( condition1 )) && command1 || commandA
pattern present. Concerning the
Code:

out="$out $word" || out=$word
statement: This merely says that if variable "$out" already exists, then define variable "out" as its own previous meaning, plus the string value of '$word'; if "out" does not already exist, than "out=$word", e.g.:
Code:

if [[ "${out}" ]]; then
        out="$out $word"
else
        out=$word
fi


grail 07-11-2016 05:45 AM

Your findings are correct and here is the same in more layman terms:

1. Variable names may start with [a-zA-Z_], so our _ could be replaced by a simple 'a', but the generally practised rule is that _ is treated as what you wish to throw away

2. It is also important to remember that read uses the IFS variable to advise the delimiter for information, so when multiple variables are provided, read will separate using the IFS information and if there
are less variables than items on the line read, all remaining items are placed in the last variable

3. (()) is specifically for arithmetic in bash, either testing or setting and calculating

4. [[ $var ]] is the same as [[ -n $var ]], which of course is your findings that if the variable is empty / null then the statement is true

Here is an additional site that i think is a must have to slowly work through after completing ABS


All times are GMT -5. The time now is 11:29 PM.