Reputation: 55
I'm struggling with this, i want to concatenate a group of lines into a single one line/row. Each line (titi/toto/tata) of my file has 2 or 3 fields separated by a ";" So my input is like this:
titi1
titi2
titi3
43;75;97
1;2;87
toto1
toto2
toto3
40;50;60
tata1
tata2
tata3
4;5;2
5;3;7
2;5;9
I need this output :
titi1;titi2;titi3;43;75;97
titi1;titi2;titi3;1;2;87
toto1;toto2;toto3;40;50;60
tata1;tata2;tata3;4;5;2
tata1;tata2;tata3;5;3;7
tata1;tata2;tata3;2;5;9
So has you can see the first 3 lines are informations (toto/tata etc...) that should be repeated for each line after that start with a number.
First my input had only one line with number so it was a grouping 4 by 4. so i searched in the forum had i found an example and did this with a getline like this :
awk '{getline b; getline c; getline d;printf("%s %s %s %s\n",$0,b,c,d)}'
But then i started to have 2 or even 3 lign with numbers... So i'm struggling doing a 'conditionnal' that understand that it should repeat the first 3 lign everytime it sees a lign starting with a numbers.
Upvotes: 4
Views: 125
Reputation: 58478
This might work for you (GNU sed):
sed -r '/;/{:a;G;s/([^\n]*)\n(.*)/\2\n\1/;s/.//;s/\s*\n/;/g;n;/;/ba;x;z;x};H;d' file
Use the hold space to store the first part of each record. When an end part of a record is encountered, append the hold space, rearrange the last part to follow the first part, remove the first newline and replace the remaining newlines by semi-colons. Print the record and if the next line is an end part of a record repeat. Otherwise, clear the hold space and append the current line to the hold space.
Upvotes: 1
Reputation: 17028
This program should so:
awk 'f&&/^[^0-9]/{b="";f=0} /^[^0-9]/{b=b$0";"} /^[0-9]/{print b$0;f=1}'
Explanation:
1. /^[^0-9]/{b=b$0";"}
2. /^[0-9]/{print b$0;f=1}
3. f&&/^[^0-9]/{b="";f=0}
$0
, set flagUpvotes: 1
Reputation: 204074
$ awk -F';' 'NF>1{print s $0; p=1; next} p{s=p=""} {s=s $0 FS}' file
titi1;titi2;titi3;43;75;97
titi1;titi2;titi3;1;2;87
toto1;toto2;toto3;40;50;60
tata1;tata2;tata3;4;5;2
tata1;tata2;tata3;5;3;7
tata1;tata2;tata3;2;5;9
wrt your original script - see http://awk.freeshell.org/AllAboutGetline for why not to use getline for this (or most other situations) and how to call getline correctly on those rare occasions when it is appropriate to do so.
Upvotes: 2
Reputation: 2491
You can try this awk :
awk -F';' 'NF==1{if(b){a=b=""};a=a$0FS;next}{b=1;$0=a$0}1' infile
And more understandable
awk -F ';' '
NF==1 {
if ( b ) {
a = b = ""
}
a = a $0 FS
next
}
{
b = 1
$0 = a $0
} 1
' infile
Upvotes: 1
Reputation: 133650
Could you please try following.
awk '
{
sub(/ +$/,"")
}
/^[a-zA-Z]+/{
if(val && flag){
val=""
}
val=val?val ";" $0:$0
flag=""
next
}
{
flag=1
print val ";" $0
}' Input_file
Solution 2nd: In case your Input_file could have last line as tot
etc and you want to print it too then use following.
awk '
{
sub(/ +$/,"")
}
/^[a-zA-Z]+/{
if(val && flag){
val=""
}
val=val?val ";" $0:$0
flag=""
next
}
{
flag=1
print val ";" $0
}
END{
if(val && !flag){
print val
}
}' Input_file
Upvotes: 2