2

I've a file.txt written in this way:

0 
0.421915 0.420615 192000
0.420397 0.420802 192000
1
0.423915 0.423681 768000
0.421658 0.421474 768000

and I'd like to take the line with only one column and the following one. Is it ok to use awk and how can I do it?

Thank you!

theozh
  • 22,244
  • 5
  • 28
  • 72
ila
  • 19
  • 2

4 Answers4

4

Short awk approach:

awk 'NF==1 && (getline nl)>0{print $0 ORS nl}' file

The output:

0
0.421915 0.420615 192000
1
0.423915 0.423681 768000

  • NF==1 - considering only lines with one column

  • getline nl - getting the next line and assigning it to variable nl (next line)

  • (getline nl)>0 - the getline command returns 1 if it finds a record and 0 if it encounters the end of the file

  • print $0 ORS nl - print the line with only one column and the following one (as required)

RomanPerekhrest
  • 88,541
  • 4
  • 65
  • 105
  • To explain the solution - NF==1 checks to see if there is one field in the record/line with a default field delimiter of space. When this condition is met, the next line is read into the variable nl and then the current line is printed ($0) along with the default record separator - RS (carriage return) and then the variable nl. – Raman Sailopal May 19 '17 at 11:44
  • @RamanSailopal, so you should have been told that before downvoting – RomanPerekhrest May 19 '17 at 11:45
  • Sorry Roman, it wasn't me downgrading, I pressed the poxy carriage return/post by accident. I've just edited – Raman Sailopal May 19 '17 at 11:48
  • @RamanSailopal, I've recovered it. That was tricky, don't do that ) – RomanPerekhrest May 19 '17 at 11:50
  • ok, that works. and if I want not the first following row but the second one? – ila May 19 '17 at 12:45
  • @ila, if you show the desired result, I'll try to help – RomanPerekhrest May 19 '17 at 12:46
  • I'd like something as: ****0.420397 0.420802 192000 ****0.421658 0.421474 768000 (*** means a new linea, sorry I'm new) The second lines after the one with just NF=1. Thank you – ila May 19 '17 at 12:50
  • @ila, should it be printed along with main line (which has one column)? Just this 2 lines: `0.420397 0.420802 192000 0.421658 0.421474 768000 ` ? – RomanPerekhrest May 19 '17 at 13:00
  • Make sure to read and fully understand everything discussed at http://awk.freeshell.org/AllAboutGetline if you're considering opening the `getline` can of worms. In this case, for example, if your input file ended in a single field then the `getline` would quietly fail so `nl` would remain it's previous value and you'd end up copying the second-last line into the output after the last line, thereby producing output that looks perfectly correct but in fact is completely wrong and you got no indication a problem had occurred. There are other issues too - just read the article then don't do it. – Ed Morton May 19 '17 at 14:41
  • 1
    @EdMorton, thanks, your supposition about *input file ended in a single field* was reasonable (I didn't think of that). Fixed – RomanPerekhrest May 19 '17 at 14:49
  • Youre welcome. It now wont print the last line at all if it's a single field though. There's just too much to consider when you use getline (unless you **really** need it) - all these rainy day cases just come crawling out of the woodwork and bite you later. And you can't easily enhance it - try adding a simple `print |"cat>&2"` to output every line to stderr for debugging for example. btw it won;t change the output in this case but in general you should be using `ORS` instead of `RS` in output statements (since that's what it is for). – Ed Morton May 19 '17 at 14:51
2

I would do it with grep :

grep -E -A 1 "^[0-9]+$" yourfile.txt

Esteban
  • 1,752
  • 1
  • 8
  • 17
  • you no need to use `*` because it matches the empty line as well – Shakiba Moshiri May 19 '17 at 11:01
  • You're right, i'll change it to a `+`, thank you for pointing it out – Esteban May 19 '17 at 11:04
  • Although this should work, the input text posted by the OP has a space at the end of the first line which would cause this reg exp to fail to detect. Instead, using `"^[0-9]+[ ]*$"` should work, but remember also that `grep` will introduce a `--` separator line between successive matches so you'd need to add something like `| grep -v "\-\-"` to remove them. – Component 10 May 19 '17 at 11:47
0

You should be able to do it with:

awk 'NF==1{p=1;print$0;}NF!=1{if(p==1){print$0;p=0}}' file.txt

Output:

0 
0.421915 0.420615 192000
1
0.423915 0.423681 768000
Component 10
  • 10,247
  • 7
  • 47
  • 64
0
$ awk 'NF==1{c=2} c&&c--' file
0
0.421915 0.420615 192000
1
0.423915 0.423681 768000

See https://stackoverflow.com/a/17914105/1745001 for an explanation of that and more awk range idioms.

Community
  • 1
  • 1
Ed Morton
  • 188,023
  • 17
  • 78
  • 185