LinuxQuestions.org
Share your knowledge at the LQ Wiki.
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 05-30-2009, 06:08 PM   #1
RVF16
Member
 
Registered: May 2008
Location: Athens, Hellas
Distribution: Archlinux
Posts: 59

Rep: Reputation: 15
Read text file column by column


Hello.

I have the following text file "devicesinfo" :

Code:
071202004143 2 1.33 1-7
081002004779 1 1.32 1-5 video0 audio0 mixer0 radio0 vbi0 dsp1 dvb0
I would like to read for example the second line column by column.
Problem is that not only the field values change (except for the first column) but also the number of columns (except for the first 4).

I know i can read a specific column :
Code:
# cat devicesinfo | grep 081002004779 | awk '{print $3}'
1.32
I would like to make that $3 parametric and make a loop that reads each column value until there is none left.

Thank you.
Regards.
 
Old 05-30-2009, 06:47 PM   #2
colucix
LQ Guru
 
Registered: Sep 2003
Location: Bologna
Distribution: CentOS 6.5 OpenSuSE 12.3
Posts: 10,509

Rep: Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983
Just an idea:
Code:
#!/bin/bash
while read line
do
  count=1
  ncols=$(echo $line | wc -w)
  while [ $count -le $ncols ]
  do
    echo $line | cut -d' ' -f$count
    ((count++))
  done
done < devicesinfo
 
Old 05-30-2009, 06:54 PM   #3
Telemachos
Member
 
Registered: May 2007
Distribution: Debian
Posts: 754

Rep: Reputation: 60
Here's one way, using Perl. (You can obviously adjust to do other processing on the fields and to get the parametric value (the one you for) from a file or from the person running the program, etc.)

Code:
#!/usr/bin/env perl
use strict;
use warnings;

while (<>) {
  if (m/^081002004779/) {
    chomp; # Remove newline
    # Split line on whitespace and save into @line
    my @line = split /\s+/, $_; 
    print "In line $.:\n";

    foreach my $column (@line) {
      print "\tHere's a column: $column\n";
    }
  }
}
Also, if you know that this magic line will only occur once, you should break out of the while loop early, rather than read the rest of the file.

Last edited by Telemachos; 05-30-2009 at 06:56 PM.
 
Old 05-30-2009, 06:58 PM   #4
norobro
Member
 
Registered: Feb 2006
Distribution: Debian Sid
Posts: 792

Rep: Reputation: 331Reputation: 331Reputation: 331Reputation: 331
And here's another based on your code:
Code:
$cat awk.txt
081002009999 1 1.32 1-5 video0 audio0 mixer0 radio0 vbi0 dsp1 dvb0
081002004779 1 1.32 1-5 video0 mixer0 radio0 vbi0 dsp1 dvb0
081002008888 1 1.32 1-5 video0 audio0 mixer0 vbi0 dsp1
081002004779 1 1.32 1-5 video0 dsp1 dvb0
Code:
$cat awk.txt | grep 081002004779 | awk '{for(i = 1 ; i <= $NF ; i++)  {print '$i'; next}}' 
081002004779 1 1.32 1-5 video0 mixer0 radio0 vbi0 dsp1 dvb0
081002004779 1 1.32 1-5 video0 dsp1 dvb0
 
Old 05-30-2009, 07:18 PM   #5
RVF16
Member
 
Registered: May 2008
Location: Athens, Hellas
Distribution: Archlinux
Posts: 59

Original Poster
Rep: Reputation: 15
Thank you all.

Based upon your suggestion norobro i did the following as i wanted to manipulate each value as read :

Code:
#!/bin/bash

x=$(cat devicesinfo | grep 081002004779 | awk '{ print NF }')

for i in $(seq 1 $x)
  do
    y=$(cat devicesinfo | grep 081002004779 | awk '{j='$i'}{print $j}')
    echo $y
  done

Last edited by RVF16; 05-30-2009 at 07:21 PM.
 
Old 05-30-2009, 07:38 PM   #6
ghostdog74
Senior Member
 
Registered: Aug 2006
Posts: 2,697
Blog Entries: 5

Rep: Reputation: 244Reputation: 244Reputation: 244
Quote:
Originally Posted by colucix View Post
Just an idea:
Code:
#!/bin/bash
while read line
do
  count=1
  ncols=$(echo $line | wc -w)
  while [ $count -le $ncols ]
  do
    echo $line | cut -d' ' -f$count
    ((count++))
  done
done < devicesinfo
if using bash in OP's case, no need to call wc or cut.
Code:
exec < file
read line1
read line2
set -- $line2
for items in $@
do
    echo $items
done
 
Old 05-30-2009, 07:40 PM   #7
ghostdog74
Senior Member
 
Registered: Aug 2006
Posts: 2,697
Blog Entries: 5

Rep: Reputation: 244Reputation: 244Reputation: 244
Quote:
Originally Posted by RVF16 View Post
Thank you all.

Based upon your suggestion norobro i did the following as i wanted to manipulate each value as read :

Code:
#!/bin/bash

x=$(cat devicesinfo | grep 081002004779 | awk '{ print NF }')

for i in $(seq 1 $x)
  do
    y=$(cat devicesinfo | grep 081002004779 | awk '{j='$i'}{print $j}')
    echo $y
  done
your code is inefficient as it uses cat/grep/awk and at the same time calling them again in the for loop. Just one awk command will suffice. Awk replaces the use of cat/grep/sed so there is no need to use them when using awk
Code:
# awk 'NR==2{$1=$1;print }' OFS="\n" file
081002004779
1
1.32
1-5
video0
audio0
mixer0
radio0
vbi0
dsp1
dvb0
 
Old 05-31-2009, 03:48 AM   #8
RVF16
Member
 
Registered: May 2008
Location: Athens, Hellas
Distribution: Archlinux
Posts: 59

Original Poster
Rep: Reputation: 15
Quote:
your code is inefficient as it uses cat/grep/awk and at the same time calling them again in the for loop. Just one awk command will suffice. Awk replaces the use of cat/grep/sed so there is no need to use them when using awk
Quite right.
Thank you.
 
Old 05-31-2009, 04:00 AM   #9
colucix
LQ Guru
 
Registered: Sep 2003
Location: Bologna
Distribution: CentOS 6.5 OpenSuSE 12.3
Posts: 10,509

Rep: Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983Reputation: 1983
Quote:
Originally Posted by ghostdog74 View Post
if using bash in OP's case, no need to call wc or cut.
Thank you Ghostdog, I forgot about set -- to unset positional parameters. You're the best!
 
Old 05-31-2009, 05:45 AM   #10
Telemachos
Member
 
Registered: May 2007
Distribution: Debian
Posts: 754

Rep: Reputation: 60
Quote:
Originally Posted by ghostdog74 View Post
if using bash in OP's case, no need to call wc or cut.
Code:
exec < file
read line1
read line2
set -- $line2
for items in $@
do
    echo $items
done
It seems to me that neither Colucix's version nor this one does quite what the OP asked for. Colucix's treats every line the same way, ignoring the request to only process lines starting with '081002004779'. Ghostdog's assumes that the relevant line is on line 2 (and appears only once).

The OP's use of grep originally suggests that in a real sample, he may have no idea which line or lines begin with the magic '081002004779'.
 
Old 05-31-2009, 05:54 AM   #11
ghostdog74
Senior Member
 
Registered: Aug 2006
Posts: 2,697
Blog Entries: 5

Rep: Reputation: 244Reputation: 244Reputation: 244
Quote:
Originally Posted by Telemachos View Post
Ghostdog's assumes that the relevant line is on line 2 (and appears only once).
well, that's because he says in his first post its the second line

Quote:
The OP's use of grep originally suggests that in a real sample, he may have no idea which line or lines begin with the magic '081002004779'.
its not difficult implementing a check
Code:
while read line
do
    case $line in
    *081002004779* ) 
        set -- $line
        for items in $@
        do
            echo $items
        done
        ;;
    esac
done < file
same with the awk
Code:
awk '/081002004779/{....}' file
 
Old 05-31-2009, 07:16 AM   #12
Telemachos
Member
 
Registered: May 2007
Distribution: Debian
Posts: 754

Rep: Reputation: 60
Quote:
Originally Posted by ghostdog74 View Post
well, that's because he says in his first post its the second line
Well, yes and no. He said:
Quote:
I would like to read for example the second line column by column.
Problem is that not only the field values change (except for the first column) but also the number of columns (except for the first 4).
But yeah, I didn't mean that it was hard, only that it was part of the original problem.
 
  


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
Concatenate column 1 and column 2 of related lines cgcamal Programming 4 11-20-2008 10:43 AM
Swap column of text file kushalkoolwal Programming 4 09-05-2008 11:30 AM
How to parse text file to a set text column width and output to new text file? jsstevenson Programming 12 04-23-2008 02:36 PM
ripping a column from a text file dominant Linux - Newbie 1 01-31-2006 04:15 AM
loading from text file using column width spyghost Programming 5 11-03-2003 01:34 PM

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

All times are GMT -5. The time now is 05:40 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