Reputation: 339
I would like to exchange columns (or variables in ( )). If a line starts with "FD1", variables in () need to shift toward the right. The rightmost variable goes to the leftmost.
For example, FD1 DFF_0(CK,G5,G10); --> FD1 DFF_0(G10,CK,G5);
For the other lines, variables in () need to shift toward the left.
Myfile.txt:
FD1 DFF_0(CK,G5,G10);
FD1 DFF_1(CK,G6,G11);
IV NOT_0(G14,G0);
IV NOT_1(G17,G11);
AN2 AND2_0(G8,G14,G6);
ND2 NAND2_0(G9,G16,G15);
NR2 NOR2_0(G10,G14,G11);
NR2 NOR2_1(G11,G5,G9);
Outfile.txt:
FD1 DFF_0(G10,CK,G5);
FD1 DFF_1(G11,CK,G6);
IV NOT_0(G0,G14);
IV NOT_1(G11,G17);
AN2 AND2_0(G14,G6,G8);
ND2 NAND2_0(G16,G15,G9);
NR2 NOR2_0(G14,G11,G10);
NR2 NOR2_1(G5,G9,G11);
I know a basic of SED that can replace globally, sed 's/original/new/g' file.txt, but I think my problem is a conditional shift.
Any help is appreciated.
Upvotes: 2
Views: 117
Reputation: 67467
awk
to the rescue!
awk -F'[()]' 'function rotateLeft(x)
{return gensub(/([^,]+),(.*)/,"\\2,\\1",1,x)}
function rotateRight(x)
{return gensub(/(.*),([^,]+)/,"\\2,\\1",1,x)}
{print $1 "(" (/^FD1/?rotateRight($2):rotateLeft($2)) ")" $3}'
FD1 DFF_0(G10,CK,G5);
FD1 DFF_1(G11,CK,G6);
IV NOT_0(G0,G14);
IV NOT_1(G11,G17);
AN2 AND2_0(G14,G6,G8);
ND2 NAND2_0(G16,G15,G9);
NR2 NOR2_0(G14,G11,G10);
NR2 NOR2_1(G5,G9,G11);
UPDATE
Perhaps simpler this way
$ awk -F'[()]' 'function rotate(left,x) {
one="([^,]+)"
rest="(.*)"
regex=left?(rest "," one):(one "," rest);
return gensub(regex,"\\2,\\1",1,x)}
{print $1 "(" rotate(/^FD1/,$2) ")" $3}' file
Upvotes: 1
Reputation: 133458
Solution 1st: If you want to make the changes only for the lines which start from string FD1
then following may help you on same.
awk -F'[),(]' ' ##Creating ) comma and ( as field separators in each line of Input_file here by -F option of awk.
/^FD1/{ ##Checking if a line starts from FD1 then do following.
print $1"("$4","$2","$3");";##Printing the 1st column then ( then 4th column , 2nd column , 3rd column. I will explain further how columns will be seen here in another snippt of code.
next ##next will skip all further statements.
}
1 ##Mentioning 1 will print the lines.
' Input_file ##Mentioning the Input_file name here.
How to see the field's with their number as follows, so that you can understand above printing thing. I am running only for very first line to make you understand.
awk -F'[),(]' 'NR==1{for(i=1;i<=NF;i++){print "field number:",i OFS "field value:",$i}}' Input_file
field number: 1 field value: FD1 DFF_0
field number: 2 field value: CK
field number: 3 field value: G5
field number: 4 field value: G10
field number: 5 field value: ;
Solution 2nd: If you want to make changes on all of the lines then following may help you on same.
awk -F'[),(]' ' ##Creating ) comma and ( as field separators in each line of Input_file here by -F option of awk.
NF==5{ ##Checking if number of fields in a line are 5.
print $1"("$4","$2","$3");";##Printing 1st field ( 4th field comma 2nd field comma 3rd field ) here.
next ##next is awk built-in variable which skips all further statements.
}
NF==4{ ##Checking if number of fields are 4 in a line.
print $1"("$3","$2");"; ##printing $1 ( $3 comma $2 ); here.
}' Input_file ##Mentioning Input_file name here.
Also in case if you want to save the output into Input_file itself then append > temp_file && mv temp_file Input_file
to above codes and it should fly then.
Upvotes: 2
Reputation: 728
sed -n -r -e '/^FD1/s/\((.*),([^,]*)\)/(\2,\1)/p' -e '/^FD1/!s/\(([^,]*),(.*)\)/(\2,\1)/p' Myfile.txt
Upvotes: 1