Read text file and store the info into variable

44,543

Solution 1

It looks like sci.txt doesn't end in a new line character. As explained in man ksh, the read builtin reads up to the first newline character by default:

  read [ -ACSprsv ] [ -d delim] [ -n n] [ [ -N n] [ [ -t  timeout]  [  -u
   unit] [ vname?prompt ] [ vname ... ]
          The  shell  input  mechanism.  One line is read and is broken up
          into fields using the characters  in  IFS  as  separators.   The
          escape  character,  \, is used to remove any special meaning for
          the next character and for line  continuation.   The  -d  option
          causes  the  read  to  continue  to the first character of delim
          rather than new-line.

So, unless you use -d, it will be looking for a newline character. If your file doesn't have one, it will not actually read anything. To illustrate:

$ printf 'demo1|demo2|demo3\n' > sci.newline
$ printf 'demo1|demo2|demo3' > sci.nonewline

$ cat foo.sh
#!/usr/bin/ksh
for file in sci.newline sci.nonewline; do
    echo "Running on: $file"
    while IFS='|' read -r fdate rdate dcname
    do
        echo "$fdate $rdate $dcname"
    done < "$file"
done

Running this script returns the expected output on sci.newline but nothing for sci.nonewline:

$ foo.sh < sci.nonewline 
Running on: sci.newline
demo1 demo2 demo3
Running on: sci.nonewline

So, if your file ends with a newline (\n), everything should work as expected.


Now, the reason your echo statement works outside the loop is because the loop is never even run. When read doesn't encounter a \n character, it returns a non-0 (failure) exit status. The while SOMETHING; do construct will run only as long as SOMETHING is successful. Because read fails, the loop is never run and the echo inside the loop isn't executed. Instead, the script will run the read command and assign the variables and then, since the read returns failure, it will move on to the next part. That's why the next echo, the one outside the loop works as expected.

Solution 2

while IFS=" ," read a b c; do
    echo a: $a b: $b c: $c
done < SCI.txt
Share:
44,543

Related videos on Youtube

Siddharth Ramakrishnan
Author by

Siddharth Ramakrishnan

Updated on September 18, 2022

Comments

  • Siddharth Ramakrishnan
    Siddharth Ramakrishnan almost 2 years

    I have a text file in which the records are in any one of the formats below:

    SCI.txt

    12-12-1990
    12-12-1991
    CSE Department
    

    Or

    12-12-1990,12-12-1991,CSE Department
    

    I want them to be stored in 3 variables

    a,b,c
    

    I am looking for reading a txt file and storing the values into variable using shell script (ksh).

    --- Update ---

    I have nearly tried all the methods which are available over the internet. I couldnt able to get them worked.

    Right now I am trying this method.

    #!/usr/bin/ksh
    #reading the file content and storing in variable
    _input="sci.txt"
    while IFS='|' read -r fdate rdate dcname
    do
       echo "$fdate $rdate $dcname"
    done < "$_input"
    

    sci.txt content as follows

    demo1|demo2|demo3
    

    But I am not getting any output for the above method.

  • Siddharth Ramakrishnan
    Siddharth Ramakrishnan almost 8 years
    This worked. I am so stupid and thought echo is not printing anything.
  • Siddharth Ramakrishnan
    Siddharth Ramakrishnan almost 8 years
    Thanks, I got the desired answer. But whats the difference between these "echo "a:$a b:$b c:$c"" and "echo "$a $b $c""
  • terdon
    terdon almost 8 years
    @SiddharthRamakrishnan nothing, really. Just that echo "b:$b" will print an extra b: that helps you identify which variable is being printed. So, if $b is foo, echo "b:$b" will print b:foo while echo "$b" will only print foo.
  • Stéphane Chazelas
    Stéphane Chazelas almost 8 years
    That doesn't explain why the code in the OP's question doesn't work though. It works for me provided demo1|demo2|demo3 is terminated by a newline character.
  • terdon
    terdon almost 8 years
    @StéphaneChazelas since I'm sure you know, could you explain why the echo $vars will work outside the loop? I assume it has something to do with read seeing the eof but I don't understand the mechanics well enough to explain it.
  • Stéphane Chazelas
    Stéphane Chazelas almost 8 years
    @SiddharthRamakrishnan echo could print nothing if $fdate starts with \c. Generally, you want to use printf '%s\n' "..." instead of echo for arbitrary data. Here, the fact that it works outside of the loop suggests the line is not terminated (read returns a non-zero exit status because it can't read a complete line, so you don't enter the loop). Best would be to fix your input so it contains a full line of text. If not use while IFS='|' read -r a b c || [ -n "$a$b$c" ] though that could still fail if the unterminated line contains just ||
  • terdon
    terdon almost 8 years
    @StéphaneChazelas but if the loop is skipped, why are the variables set outside it?
  • Stéphane Chazelas
    Stéphane Chazelas almost 8 years
    @terdon, in printf foo | read a, read does set $a to foo but exits with a non-zero exit status. Try a=bar; printf foo | { read a; echo "$?: $a"; }