LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
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 01-07-2011, 11:47 AM   #1
vcmota
LQ Newbie
 
Registered: Jan 2011
Posts: 4

Rep: Reputation: 0
how to add blank lines whenever the value of a given column alters in a data file?


Please, somebody help me, I am dying here... All I want is a command that reads one data file with several columns and prints it in another one. However, whenever the value in one specific column alters, it prints one empty line in the new file. For example, consider the file

2.54000000 2.54000000
2.54000000 2.54000000
2.54000000 2.54000000
2.54000000 2.56000000
2.54000000 2.56000000
2.54000000 2.56000000
2.54000000 2.58000000
2.54000000 2.58000000
2.54000000 2.58000000
2.54000000 2.60000000
2.54000000 2.60000000
2.54000000 2.60000000
2.56000000 2.56000000
2.56000000 2.56000000
2.56000000 2.56000000
2.56000000 2.58000000
2.56000000 2.58000000
2.56000000 2.58000000
2.56000000 2.60000000
2.56000000 2.60000000
2.56000000 2.60000000

what I need is a command that return the file

2.54000000 2.54000000
2.54000000 2.54000000
2.54000000 2.54000000

2.54000000 2.56000000
2.54000000 2.56000000
2.54000000 2.56000000

2.54000000 2.58000000
2.54000000 2.58000000
2.54000000 2.58000000

2.54000000 2.60000000
2.54000000 2.60000000
2.54000000 2.60000000

2.56000000 2.56000000
2.56000000 2.56000000
2.56000000 2.56000000

2.56000000 2.58000000
2.56000000 2.58000000
2.56000000 2.58000000

2.56000000 2.60000000
2.56000000 2.60000000
2.56000000 2.60000000

Kills me is that this problem seems to have a simple solution, a simple bash command or a simple combination of bash commands rather than an elaborated script, which I can't see... Thank you all very much!
 
Old 01-07-2011, 12:32 PM   #2
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Arch + Xfce
Posts: 6,852

Rep: Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037
It could certainly be done easily in awk as well, but here's my first go at a bash-only solution:
Code:
#!/bin/bash

while read line; do

     if [[ ! ${line#* } = ${prev:-${line#* }} ]] ; then
          echo -e "\n$line"
     else
          echo "$line"
     fi

prev="${line#* }"

done <infile.txt >outfile.txt

exit 0
Edit: Here's a slightly modified version that allows you to specify whichever column you want, simply by changing the command used in the test variable.
Code:
#!/bin/bash

while read line; do

test="$( cut -d" " -f3 <<<"$line" )" # using cut, for example

     if [[ ! $test = ${prev:-$test} ]] ; then
          echo -e "\n$line"
     else
          echo "$line"
     fi

prev="$test"

done <infile.txt >outfile.txt

exit 0

Last edited by David the H.; 01-07-2011 at 12:51 PM. Reason: as stated
 
Old 01-08-2011, 01:26 AM   #3
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Arch
Posts: 10,040

Rep: Reputation: 3204Reputation: 3204Reputation: 3204Reputation: 3204Reputation: 3204Reputation: 3204Reputation: 3204Reputation: 3204Reputation: 3204Reputation: 3204Reputation: 3204
As the man said, awk can do it too:
Code:
awk 'BEGIN{printf "Enter column number: ";getline col < "-"}NR != 1 && $col != old{print ""}{old = $col}1' file
This includes the request for a column number. If you are not interested in being requested, delete the BEGIN and prior to first quote put the following:
Code:
-vcol=<number>
Where number is again the column you wish to change on.
 
1 members found this post helpful.
Old 01-08-2011, 08:20 PM   #4
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Arch + Xfce
Posts: 6,852

Rep: Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037
Grail, that's a very interesting solution. I didn't know you could have awk prompt for user input. Thanks for teaching me something new.
 
Old 01-10-2011, 07:52 AM   #5
vcmota
LQ Newbie
 
Registered: Jan 2011
Posts: 4

Original Poster
Rep: Reputation: 0
Grail and David, thank you both very much for your help. I gave up of looking for a simple command after sometime and decided to wrote an script using gawk. It is not so simple and elegant as the solution that Grail proposes (I am a beginner in the world of programming...), but it works fine. I put it in my bin folder, and now I have a simple command after all. If you guys are interested I can post it here. Thank you very much again!
 
Old 01-10-2011, 06:25 PM   #6
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Arch
Posts: 10,040

Rep: Reputation: 3204Reputation: 3204Reputation: 3204Reputation: 3204Reputation: 3204Reputation: 3204Reputation: 3204Reputation: 3204Reputation: 3204Reputation: 3204Reputation: 3204
Always interested to see a solution Please mark question as SOLVED once you have one.
 
Old 01-11-2011, 07:07 AM   #7
vcmota
LQ Newbie
 
Registered: Jan 2011
Posts: 4

Original Poster
Rep: Reputation: 0
My solution

Ok Grail, this is my solution:

awk -v column=$1 -v spaces=$2 '!/^$/{ ++i
if(i == 1) {
lfield[i]=$0
field[i]=$column
getline
++i
lfield[i]=$0
field[i]=$column}
else{
lfield[i]=$0
field[i]=$column}
if(field[i-1] != field[i]){
print lfield[i-1]
j=0
while (j <= spaces-1){
print ""
++j}
}
else{
print lfield[i-1]}
}
END {print lfield[i]}' $3


It reads the column and allow you to chose the number of spaces you want. This is useful for pipe, and also if for example you relies on gnuplot for plotting data (my case), since 2 spaces are interpreted as separation between two data blocks and 1 space is the requested separation in order to do 3 dimensional grid points plots. As I said, it is not elegant and simple as your solution (I am a newbie in awk), but it works. By the way, could you indicate me any good manual for awk? All the manuals I could find in google are after all exactly the same (http://www.cs.unibo.it/~renzo/doc/awk/nawkA4.pdf) and many details of the language are not too clear (the use of getline for example).
 
Old 01-11-2011, 07:51 AM   #8
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Arch
Posts: 10,040

Rep: Reputation: 3204Reputation: 3204Reputation: 3204Reputation: 3204Reputation: 3204Reputation: 3204Reputation: 3204Reputation: 3204Reputation: 3204Reputation: 3204Reputation: 3204
The following is my goto page when I am stuck / forget something:

http://www.gnu.org/manual/gawk/html_node/index.html

I would probably point out that your opening test seems a bit meaningless unless your data has blank lines?

As you are still learning, here is all you needed in your code whilst keeping most of the same constructs (I did change while to for as you can probably see it is the same process):
Code:
awk -v column=$1 -v spaces=$2 '!/^$/{
    lfield[++i]=$0
    field[i]=$column
    if(i == 1) {
        next
    }

    print lfield[i-1]

    if(field[i-1] != field[i])
        for(j=0; j <= spaces-1; j++)
            print ""
}
END {print lfield[i]}' $3
 
Old 01-11-2011, 10:41 AM   #9
vcmota
LQ Newbie
 
Registered: Jan 2011
Posts: 4

Original Poster
Rep: Reputation: 0
Grail, thank you again for the help. I appreciate the changes you made and I am going to use them. Yes, I need the opening because the file will certainly have blank lines in case of pipe. That is, in case I need to give spaces regarding two columns, after the first usage of the command I will have blank lines, which must be ignored in executing the command for the second time, like this:

myscript 2 2 file.dat | myscript 1 2
 
Old 01-11-2011, 08:47 PM   #10
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Arch
Posts: 10,040

Rep: Reputation: 3204Reputation: 3204Reputation: 3204Reputation: 3204Reputation: 3204Reputation: 3204Reputation: 3204Reputation: 3204Reputation: 3204Reputation: 3204Reputation: 3204
A perhaps simpler way then is to use NF. Just put those to letters in place of - !/^$/

This works as everything in front of curly braces is evaluated as an expression where zero is false and all else is true.
NF = 0 on lines with no fields
NF > 0 on all other lines
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

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
Replace data of one column with data on other file corresponding to transaction ID saurabhmehan Linux - Newbie 1 12-23-2010 01:19 AM
Concatenate column 1 and column 2 of related lines cgcamal Programming 4 11-20-2008 10:43 AM
how to get the second column and first row data from a file??? loplayers Linux - Newbie 3 11-05-2007 07:35 PM
How do i remove blank lines from a file? kakho Programming 1 04-15-2004 03:57 AM
Replace blank/almost blank lines in file Wynd Linux - General 3 01-27-2004 04:49 PM

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

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

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