LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 07-15-2005, 11:29 AM   #1
km4hr
Member
 
Registered: Aug 2003
Posts: 39

Rep: Reputation: 15
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
 
Old 07-15-2005, 11:32 AM   #2
rockytriton
LQ Newbie
 
Registered: Jul 2005
Posts: 9

Rep: Reputation: 0
have you tried to type "tag1 this is" with the quotes as the input?
 
Old 07-15-2005, 01:34 PM   #3
traene
Member
 
Registered: Jan 2005
Distribution: Archlinux, Debian, Centos
Posts: 222

Rep: Reputation: 35
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.
 
Old 07-15-2005, 03:22 PM   #4
km4hr
Member
 
Registered: Aug 2003
Posts: 39

Original Poster
Rep: Reputation: 15
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.
 
Old 07-16-2005, 10:37 AM   #5
eddiebaby1023
Member
 
Registered: May 2005
Posts: 378

Rep: Reputation: 33
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

Last edited by eddiebaby1023; 07-16-2005 at 10:39 AM.
 
Old 07-21-2005, 12:31 PM   #6
km4hr
Member
 
Registered: Aug 2003
Posts: 39

Original Poster
Rep: Reputation: 15
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.
 
Old 07-21-2005, 02:48 PM   #7
keefaz
LQ Guru
 
Registered: Mar 2004
Distribution: Slackware
Posts: 6,552

Rep: Reputation: 872Reputation: 872Reputation: 872Reputation: 872Reputation: 872Reputation: 872Reputation: 872
From your example : " 1 23"
You mean 1 is in second column and 23 in the third ?
 
Old 07-22-2005, 07:08 AM   #8
km4hr
Member
 
Registered: Aug 2003
Posts: 39

Original Poster
Rep: Reputation: 15
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.
 
Old 07-22-2005, 07:41 AM   #9
keefaz
LQ Guru
 
Registered: Mar 2004
Distribution: Slackware
Posts: 6,552

Rep: Reputation: 872Reputation: 872Reputation: 872Reputation: 872Reputation: 872Reputation: 872Reputation: 872
Of course there are many ways to keep the line intact...

Code:
IFS='
'
for line in $(cat file); do
    echo $line
done
 
Old 07-25-2005, 12:49 PM   #10
km4hr
Member
 
Registered: Aug 2003
Posts: 39

Original Poster
Rep: Reputation: 15
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
 
Old 07-25-2005, 08:41 PM   #11
chrism01
LQ Guru
 
Registered: Aug 2004
Location: Sydney
Distribution: Rocky 9.2
Posts: 18,359

Rep: Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751
As eddiebaby1023 implied, this is the sort of thing awk is designed for....
 
Old 07-26-2005, 04:52 AM   #12
keefaz
LQ Guru
 
Registered: Mar 2004
Distribution: Slackware
Posts: 6,552

Rep: Reputation: 872Reputation: 872Reputation: 872Reputation: 872Reputation: 872Reputation: 872Reputation: 872
km4hr, look closely...
Code:
IFS='
'
Also could you post some lines of your data file ?

Last edited by keefaz; 07-26-2005 at 04:57 AM.
 
Old 07-26-2005, 09:33 AM   #13
km4hr
Member
 
Registered: Aug 2003
Posts: 39

Original Poster
Rep: Reputation: 15
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?
 
Old 07-26-2005, 11:20 AM   #14
keefaz
LQ Guru
 
Registered: Mar 2004
Distribution: Slackware
Posts: 6,552

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

Try man bash and search for IFS and Word Splitting
 
Old 07-26-2005, 12:34 PM   #15
schneidz
LQ Guru
 
Registered: May 2005
Location: boston, usa
Distribution: fedora-35
Posts: 5,313

Rep: Reputation: 918Reputation: 918Reputation: 918Reputation: 918Reputation: 918Reputation: 918Reputation: 918Reputation: 918
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
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
BASH script – reading and writing variables to a separate file morrolan Programming 10 09-20-2005 07:45 AM
Reading a conf file from a BASH script dinolinux Programming 5 08-03-2005 04:18 AM
Need help reading text file in bash script scilec Programming 3 11-25-2004 06:44 PM
Bash script - reading from text file twantrd Programming 4 11-24-2004 12:38 AM
reading file, bash script marri Programming 3 11-15-2004 09:13 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 12:54 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration