How can i join three lines into one in unix?

Hi all,

I am trying to merge three lines into one in my unix text file.

My text file sis omething like this.

xxxxxxxxx
yyyyyyyyyyy
zzz
aaaaaaaaa
bbbbbb
ccccc

Expected out put is

xxxxxxxxx yyyyyyyyyyy zzz
aaaaaaaaa bbbbbb ccccc

I tried with awk as shown below.

awk '{printf $0 " "; getline; print $0}'

But it is working only for merging two lines. Please help me in modifying this awk or any other alternative for this?

HTH

$ cat file.txt
xxxxxxxxx
yyyyyyyyyyy
zzz
aaaaaaaaa
bbbbbb
ccccc
$ perl -pi -e 's/\n/ / if $.%3' file.txt
$ cat file.txt
xxxxxxxxx yyyyyyyyyyy zzz
aaaaaaaaa bbbbbb ccccc

See if this works.

awk '{
if (NR % 3)
printf("%s ", $0)
else
printf("%s\n", $0)
}' file

Thanks lathavim..it worked perfectly..Pludi, i am looking for a shell command..anyway thanks for your reply.

You do know that Perl is as much a "shell command" as awk (both aren't shell built-ins but external commands), and both commands given do the same thing.

Hi, I was reading this.. this work perfect, but I need something slightly different. I need print in the same line two lines if it finds a pattern ( a string in the first line). I am trying different things with awk.. but cant get it to work :frowning:

It would be something like

select bla bla
update bla bla
bla bla
insert into bla bla

and the resulting file must find "update" and then print that line and the next one altogether, like:

select bla bla
update bla bla bla bla
insert into

Any help would be great.....

try this...

awk '{if (NR%3) {ORS="";print " "$0} else {ORS="\n";print " "$0}}'
 file

Try this for printing the line with pattern, line above and the next line.
awk '/update/{where=NR;print}NR==where+1 && where!=0 {print}'

nawk 'c&&!--c;/update/{c=1;printf $0 OFS}' myFile

HI Rdhanek,

you can make use of this code:

paste -s -d "  \n" filename

output:

xxxxxxxxx yyyyyyyyyyy zzz
aaaaaaaaa bbbbbb ccccc

Regards,
Sanjay

Thank you very much for your quick response. It does not quite yet what I am looking for.. I need only two lines, for what I just changed "NR%2" like this:

awk '{if (NR%2) {ORS="";print " "$0} else {ORS="\n";print " "$0}}'
 file

The problem is, that I want to print like this only when it meets a patter, for example:

input:

select <something><something>
update <something><something>
<something><something>
insert into <something><something>

output:

select <something><something>
update <something><something><something><something>
insert into <something><something>

I just cant figure out how to do it.. I dont know if I have to use something like

/update/{ if (NR%2) ..

or

if((NR%2) && ($1=="nueva"))

both just doesnt work...

---------- Post updated at 11:08 AM ---------- Previous update was at 11:01 AM ----------

Thanks, this works great, but just print the two lines I want in one, that's perfect :slight_smile: but it doesnt print the rest of the file. How to make this work then?

nawk 'c&&!--c{print;next};/update/{c=1;printf $0 OFS;next}1' myFile

if the total number of lines is in multiples of 3, then

sed -n 'N;N;s/\n/ /gp' FILENAME

Congratulations, this works 100% perfect. Thanks so much. I will keep studying the uses of awk, which are quite extensive.
I really appreaciate your help, man.
:b:

Regards.

---------- Post updated at 01:10 PM ---------- Previous update was at 11:56 AM ----------

Just one more question regarding your impressive advanced knowledge of awk:

I have appended my line when found the word "update", but I want this to happen only when next line doesnt contain either the string "alter table" or "insert into".

Like,

input:

select <something><something>
update <something><something>
<something><something>
insert into <something><something>
select <something><something>
update <something><something>
alter table <something><something>
update <something><something>
insert into <something><something>

output:

select <something><something>
update <something><something><something><something>
insert into <something><something>
select <something><something>
update <something><something>
alter table <something><something>
update <something><something>
insert into <something><something>

thank you so much.. I hope the explanation is clear enough now..

nawk 'c && !--c {print (($0 ~/(alter|insert)/)? ORS: OFS) $0;next};/update/{c=1;printf $0;next}1' myFile

Apologies. I have just re-edited the last post, I hope it's easier to understand now.

Thanks.

Perfect, thanks so much. I have learnt a lot. So fast answering too.. thousand times thank you.:slight_smile:

awk '{printf (/^</)?$0:ORS$0}' file

Thank you protocomm, but I had what I needed. That doesnt search for a any pattern. Thanks anyways, it's helping me to understand how awk works :slight_smile:

---------- Post updated at 11:00 AM ---------- Previous update was at 10:37 AM ----------

humm this returns what I need but I cant use it because the next line has not a reference string but the string in the line just before with the word "update" is the one I can use.

Thanks anyways :slight_smile:

---------- Post updated at 11:18 AM ---------- Previous update was at 11:00 AM ----------

I have another problem..

When I have a "create table" I have several lines after, and then ");". I want to append all those lines but I dont know how many lines would it be, so the reference would be the final ");" line. How to add this new rule to the one you made before?? :confused:

Your last statement:

nawk 'c && !--c {print (($0 ~/(alter|insert)/)? ORS: OFS) $0;next};/update/{c=1;printf $0;next}1' myFile

So, I have found something like:

input:

select <something><something>
update <something><something>
<something><something>
insert into <something><something>
select <something><something>
update <something><something>
alter table <something><something>
update <something><something>
insert into <something><something>
create table <something><something>
<something><something>
);
select <something><something>
create table <something><something>
<something><something>
<something><something>
<something><something>
);
update <something><something>

output:

select <something><something>
update <something><something><something><something>
insert into <something><something>
select <something><something>
update <something><something>
alter table <something><something>
update <something><something>
insert into <something><something>
create table <something><something><something><something>);
select <something><something>
create table <something><something><something><something><something><something><something><something>);
update <something><something>

I am sorry this has turned into a more complex stuff.. thankful again.

---------- Post updated at 12:04 PM ---------- Previous update was at 11:18 AM ----------

Another way of solving my problem would be a statement doing something just like finding a string1, deleting this line and the next lines until it finds another pattern in a line. This line that follows the other pattern wont be deleted.
If implementing this job, the last thing I requested before about "create table" wont be needed any more.
Also, if a line with just the string1 is found, delete that line.

It would be something like:

input:

select <something><something>
update <something><something>
insert into <something><something>
select <something><something>
<something><something>
<something><something>
insert into <something><something>
select <something><something>
<something><something>
 <something><something>
<something><something>
update <something><something>

output:

update <something><something>
insert into <something><something>
insert into <something><something>
update <something><something>

So I want to find the string /select/ in a line, delete it, and the next lines after, doesnt matter how many if they are not /(update | insert into)/ , for example.

Thank you.. and as I said, if doing this, I wont need to work what I said before about "create table".

---------- Post updated at 12:24 PM ---------- Previous update was at 12:04 PM ----------

That is, if I would have a pattern to say "delete this line when you find this pattern" I would simply say:

sed '/^select/,/update$/d' myfile

but the problem is that I dont want it to delete the line with update, but the line just before when it finds it :s

I keep trying.. I am really new to this awk/sed world..

Your requirement change from post to post. Try to decide what you need and post a data sample and required output.