Read text file and store the info into variable
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
Related videos on Youtube
Siddharth Ramakrishnan
Updated on September 18, 2022Comments
-
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 almost 8 yearsThis worked. I am so stupid and thought echo is not printing anything.
-
Siddharth Ramakrishnan almost 8 yearsThanks, I got the desired answer. But whats the difference between these "echo "a:$a b:$b c:$c"" and "echo "$a $b $c""
-
terdon almost 8 years@SiddharthRamakrishnan nothing, really. Just that
echo "b:$b"
will print an extrab:
that helps you identify which variable is being printed. So, if$b
isfoo
,echo "b:$b"
will printb:foo
whileecho "$b"
will only printfoo
. -
Stéphane Chazelas almost 8 yearsThat 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 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 withread
seeing theeof
but I don't understand the mechanics well enough to explain it. -
Stéphane Chazelas almost 8 years@SiddharthRamakrishnan
echo
could print nothing if$fdate
starts with\c
. Generally, you want to useprintf '%s\n' "..."
instead ofecho
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 usewhile IFS='|' read -r a b c || [ -n "$a$b$c" ]
though that could still fail if the unterminated line contains just||
-
terdon almost 8 years@StéphaneChazelas but if the loop is skipped, why are the variables set outside it?
-
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. Trya=bar; printf foo | { read a; echo "$?: $a"; }