LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   bash; reading values from a file (https://www.linuxquestions.org/questions/programming-9/bash%3B-reading-values-from-a-file-343482/)

km4hr 07-15-2005 11:29 AM

bash; reading values from a file
 
A text file has lines containing three fields; tag, description, status.
Example:
Tag Description Status
tag1 this is tag1 good <--- file contents
tag2 this is tag2 bad <---

If I use 'read' in a bash script as in following example the variable 'desc' only gets the first
word in the description. Variable 'status' gets the second word in the description:
Example:
read tag desc status
echo $tag ---> tag1
echo $desc ---> this
echo $status ---> is

How can read the full description into variable 'desc'? (desciption has variable number of words)

To say it another way, is there any way to read columns of information instead of individual fields of information? Can I combine 'cut' with 'read' somehow? Is there a way to do formatted input?

xyz

rockytriton 07-15-2005 11:32 AM

have you tried to type "tag1 this is" with the quotes as the input?

traene 07-15-2005 01:34 PM

You better define some splitting characters for your input. It seems that your description can be multiple words with white-space separation. When you say something like:
tag1;description; blurb
You may just make a
Code:

read line
tag=echo $line | cut -d; -f1
descr=echo $line | cut -d; -f2
etc.


km4hr 07-15-2005 03:22 PM

Thank's guys. I'm not at a point where it can test your solutions at the moment but I see where you're going and it looks good. I'll try it soon. Most of all I appreciate your consideration. Thanks again.

eddiebaby1023 07-16-2005 10:37 AM

If your status is always a single word, it'd be much easier to parse it as "tag status description". I've always found that if you "read" into a list of shell variables, the last one gets the rest of the line if there are more words than variables. That's in ksh (not pdksh which is an abomination), I'm not sure if bash does it this way (I could try it, but it's your problem, not mine!).

It's just occurred to me that you could use awk to read the last word of a line and reformat the data to suit your processing:
Code:

awk '{print $NF}' somefile

km4hr 07-21-2005 12:31 PM

traene,

Your solution is nearly ideal. It would be perfect if not for an inherent property of the "read" command. Unfortunately 'read' strips spaces from the beginning of the line. Since the file I'm reading doesn't include delimiters I need to split the columns based on position. The "cut" command will do that (cut -c1-3). But because "read" strips spaces at the beginning of the line the columns are not in consistent positions.

For example. Say the following two lines of text are in the input file.
" 1 23"
" 12 34"

Using 'read aline', columns in $aline become shifted as follows:
"1 23"
"12 34"

Shifting the columns makes 'cut' useless.

A way to read a line literally from a file without stripping the initial spaces is needed.
Any ideas?

thanks

Quote:

Originally posted by traene
You better define some splitting characters for your input. It seems that your description can be multiple words with white-space separation. When you say something like:
tag1;description; blurb
You may just make a
Code:

read line
tag=echo $line | cut -d; -f1
descr=echo $line | cut -d; -f2
etc.



keefaz 07-21-2005 02:48 PM

From your example : " 1 23"
You mean 1 is in second column and 23 in the third ?

km4hr 07-22-2005 07:08 AM

Quote:

Originally posted by keefaz
From your example : " 1 23"
You mean 1 is in second column and 23 in the third ?

Well, I was trying to show that lines beginning with spaces will be altered by the "read" command. That is, leading spaces will be removed. Therefore, if you're trying to cut columns of information out of the line based on character position then you can't do it because removing the leading spaces shifts the columns to the left by an amount equal to the number of spaces removed.

To say it another way, there appears to be no way to read a line of text into a shell script unaltered if any the line begin with spaces. The leading spaces will be removed by "read".

To say it yet again, there appears to be no way to read a text file into a shell script and write it out to another file so that the two files are identical, if the original file contains a space at the beginning of a line.

keefaz 07-22-2005 07:41 AM

Of course there are many ways to keep the line intact...

Code:

IFS='
'
for line in $(cat file); do
    echo $line
done


km4hr 07-25-2005 12:49 PM

Quote:

Originally posted by keefaz
Of course there are many ways to keep the line intact...

Code:

IFS='
'
for line in $(cat file); do
    echo $line
done


=========================================================
hi keefaz,

I can't get this to work. The "echo $line" statement prints each item in a row from left to right instead of the entire row.

I don't understand what the " IFS=' " is for. Maybe that's my problem.

Please suggest another of the "many ways" to do this.

thanks

chrism01 07-25-2005 08:41 PM

As eddiebaby1023 implied, this is the sort of thing awk is designed for....

keefaz 07-26-2005 04:52 AM

km4hr, look closely...
Code:

IFS='
'

Also could you post some lines of your data file ?

km4hr 07-26-2005 09:33 AM

Quote:

Originally posted by keefaz
km4hr, look closely...
Code:

IFS='
'

Also could you post some lines of your data file ?

====================================================================
Yes! That works. That's strange stuff. What does the tick on the line by itself do? My script works with or without it. I thought it was some artifact put there by mistake or something. My script doesn't complain about it being there. But it also works without it.

BTW, what's the deal with IFS. I noticed that "echo $IFS" doesn't work.
Example:
$ IFS=hello
$ echo $IFS

$
However:
$ echo "$IFS"
hello
$

Why?

Also, why do you have to set IFS inside the script. I tried setting it in the environment but the script doesn't see it. (Ex: At the command line I type " IFS=' " , " export IFS", then execute the script) How come?

keefaz 07-26-2005 11:20 AM

IFS: Internal Field Separator
(default value : <space><tab><newline>)

Try man bash and search for IFS and Word Splitting

schneidz 07-26-2005 12:34 PM

this might already be mentioned but what if you cut-awk the first column, the middle, and the last column on separate lines (man cut and awk; they can work with last feild in a line):
tag1
this is tag1
good
tag2
this is tag2
bad

then hard-code your script accordingly (you'll know that 'tag1' is on every third line but will be transparent to the user). might be more work but it could be more fun.

sorry i'm at work so i have no tested code. i'll catch up with y'all when i get home.

thanks,
schneidz


All times are GMT -5. The time now is 12:23 PM.