54

a bash commands outputs this:

Runtime Name: vmhba2:C0:T3:L14 Group State: active Runtime Name: vmhba3:C0:T0:L14 Group State: active unoptimized Runtime Name: vmhba2:C0:T1:L14 Group State: active unoptimized Runtime Name: vmhba3:C0:T3:L14 Group State: active Runtime Name: vmhba2:C0:T2:L14 Group State: active 

I'd like to pipe it to something to make it look like this:

Runtime Name: vmhba2:C0:T1:L14 Group State: active Runtime Name: vmhba3:C0:T3:L14 Group State: active unoptimized Runtime Name: vmhba2:C0:T2:L14 Group State: active [...] 

i.e. remove every other newline

I tried ... |tr "\nGroup" " " but it removed all newlines and ate up some other letters as well. thanks

2
  • 3
    tr is entirely character based: you asked tr to remove newlines and all 'G', 'r', 'o', 'u', and 'p'. Commented Mar 30, 2012 at 1:01
  • Are you looking for every other (single) newline at the end of a line, or multiple newlines like \n\n, or both? Commented Feb 10, 2020 at 23:18

8 Answers 8

104

TL;DR:

This should do it:

 ... | paste - - 

Details

paste is used to concatenate corresponding lines from files:

paste file1 file2 file3 .... 

If one of the "file" arguments is -, then lines are read from standard input.

If there are two - arguments, then paste takes 2 lines from stdin. And so on.

See the man page.

3
  • 8
    +1 - works and is elegant. (It puts a tab between the lines - paste -d ' ' - - will add a space instead if required) Commented Mar 30, 2012 at 1:20
  • 6
    Could you please explain how does the command work? Why are there two -? Thanks Commented Mar 30, 2012 at 8:55
  • 12
    paste is used to concatenate corresponding lines from files: paste file1 file2 file3 .... If one of the "file" arguments is "-", then lines are read from standard input. If there are 2 "-" arguments, then paste takes 2 lines from stdin. And so on. See the man page. Commented Mar 30, 2012 at 10:33
11

One possibility is:

awk 'ORS=NR%2?" ":"\n"' 

If the line number is evenly divisible by 2, end with a new line, otherwise, end with a space.

(Tested on: CentOS 6, GNU Awk 3.1.7)

Using sed (see explanation):

sed ':a;N;$!ba;s/\nGroup/ Group/g' 

Further reading:

1
  • The second link to linux.dsplabs.com.au is broken Commented Feb 9, 2020 at 19:44
8

If you want to use sed, there's no reason to read the whole file into memory. You can merge every other line like this:

sed 'N;s/\n/ /' inputfile 

Use any character you'd like instead of the space.

Here's another way using awk:

awk '{printf "%s", $0; if (getline) print " " $0; else printf "\n"}' inputfile 

The if/else handles the case where there is an odd number of lines in the file. Without it, the odd last line gets printed twice. Otherwise, for comparison, you could do:

awk '{printf "%s", $0; getline; print " " $0}' 
1
  • 1
    A late comment: 1) always use a format specifier for printf in case the string has percent signs, 2) to avoid the duplicated last line, set $0 to "" -- awk '{printf "%s", $0; $0=""; getline; print " " $0}' Commented Dec 10, 2012 at 21:47
4

The most idiomatic way to do it in awk is as follows:

awk 'ORS=NR%2?FS:RS' file 

It outputs:

Runtime Name: vmhba2:C0:T3:L14 Group State: active Runtime Name: vmhba3:C0:T0:L14 Group State: active unoptimized Runtime Name: vmhba2:C0:T1:L14 Group State: active unoptimized Runtime Name: vmhba3:C0:T3:L14 Group State: active Runtime Name: vmhba2:C0:T2:L14 Group State: active 

To explain it we need to define each one of the built-in variables:

  • RS record separator. Defaults to \n (new line).
  • ORS output record separator. Defaults to \n (new line).
  • FS field separator. Defaults to (space).
  • NR number of record.

As the default record separator is the new line, a record is, as default, a line.

NR%2 is the modulus of NR/2, so that it will be either 0 or 1. 0 for even lines and 1 for odd lines.

var=condition?condition_if_true:condition_if_false is the ternary operator.

All together, saying ORS=NR%2?FS:RS we are defining the output record separator:

  • if the number of record is on the form 2k + 1, that is, on even lines, then the output record separators is set to FS, that is, a space.
  • if the number of record is on the form 2k, that is, on odd lines, then the output record separators is set to RS, that is, a new line.

This way, odd lines end with a space, that is then joined with the next line. After that line, a new line is printed.

More info in Idiomatic awk.

1
  • This also cunningly relies on the fact that the expression also results in either FS or RS, which are (evidently) both truthy. If the expression returned something falsy (e.g. (ORS=...)&&0, nothing would print. Commented Mar 25, 2022 at 10:56
3

This works for me on Linux:

... | tr "\\n" " " 

This replaces an empty space for a newline character; you must escape the newline character for things to work correctly.

1
  • 1
    This removes every newline, not every other newline. Commented Feb 23, 2017 at 22:20
2

In bash:

... | while read l1; do read l2; echo "$l1 $l2"; done 
1

If Perl is an option:

perl -pe 's/\n/ / if $. % 2 == 1' file

s/\n/ / replaces newline with space
$. is the line number

-2

How about using grep ?

.. | grep -v '^Group State' 
2
  • 1
    That eliminates the alternate lines. The OP wants them appended. Commented Mar 30, 2012 at 6:51
  • Yeah, after re-reading the question I just realized that :) Commented Mar 30, 2012 at 6:52

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.