Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Duplicating last 4 columns of a file 4

Status
Not open for further replies.

hill007

Technical User
Mar 9, 2004
60
US
I have a situation where I have to duplicate the last 4 columns of a file. To make it clear here is an example:

A B C D E F G H
1 2 3 4 5 6 7 8
I J K L M N O P

Now I want to duplicate the last 4 columns of the file, so that the file looks such:

A B C D E F G H E F G H
1 2 3 4 5 6 7 8 5 6 7 8
I J K L M N O P M N O P

Any help appreaciated.

Thanks.
 
Untested but may get you started.

{
for (j=0;j<4;j++) $(NF+j+1) = $(NF+j-3)
print
}

CaKiwi
 

Code:
BEGIN{ f = " [^ ]+"; regx = f f f f "$" }

{ sub( regx, "&&" )
  print
}

 
Hi Futurelet,

Your code works fine with my above example perfectly.
Somehow when I try on my actual data it do not work. I am including a small part of my data here.

1.730000e+002 1.720000e+002 1.700000e+002 1.690000e+002 1.680000e+002 1.670000e+002 1.660000e+002 1.650000e+002 1.640000e+002 1.630000e+002
1.620000e+002 1.610000e+002 1.600000e+002 1.590000e+002 1.580000e+002 1.570000e+002 1.560000e+002 1.550000e+002 9.800000e+002 1.095000e+003
1.097000e+003 1.100000e+003 1.102000e+003 1.104000e+003 1.106000e+003 1.108000e+003 1.110000e+003 9.800000e+002 1.072000e+003 1.072000e+003
1.073000e+003 1.074000e+003 1.074000e+003 1.075000e+003 1.076000e+003 1.076000e+003 1.077000e+003 1.077000e+003 1.078000e+003 1.079000e+003
1.079000e+003 1.080000e+003 1.080000e+003 1.081000e+003 1.081000e+003 1.082000e+003 1.082000e+003 1.083000e+003 1.083000e+003 1.083000e+003
1.084000e+003 1.084000e+003 1.085000e+003 1.089000e+003 1.168000e+003 1.168000e+003 1.167000e+003 1.167000e+003 1.166000e+003 1.166000e+003
1.165000e+003 1.164000e+003 1.164000e+003 1.163000e+003 1.163000e+003 1.162000e+003 1.161000e+003 1.161000e+003 1.160000e+003 1.159000e+003
1.159000e+003 1.158000e+003 1.157000e+003 1.157000e+003 1.156000e+003 1.155000e+003 1.154000e+003 1.153000e+003 1.152000e+003 1.152000e+003
1.151000e+003 1.150000e+003 1.148000e+003 1.147000e+003 1.146000e+003 1.145000e+003 1.144000e+003 1.142000e+003 1.141000e+003 1.139000e+003
1.138000e+003 1.136000e+003 1.134000e+003 1.132000e+003 1.130000e+003 1.128000e+003 1.126000e+003 1.123000e+003 1.121000e+003 1.118000e+003
1.115000e+003 1.112000e+003 1.109000e+003 1.106000e+003 1.103000e+003 1.099000e+003 1.095000e+003 1.091000e+003 1.087000e+003 1.082000e+003
1.077000e+003 1.072000e+003 1.067000e+003 1.062000e+003 1.056000e+003 1.050000e+003 1.043000e+003 1.036000e+003 1.029000e+003 1.022000e+003
1.014000e+003 1.006000e+003 9.970000e+002 9.880000e+002 9.790000e+002 9.690000e+002 9.580000e+002 9.470000e+002 9.360000e+002 9.240000e+002
9.120000e+002 8.990000e+002 8.860000e+002 8.720000e+002 8.580000e+002 8.430000e+002 8.280000e+002 8.130000e+002 7.970000e+002 7.810000e+002
7.660000e+002 7.500000e+002 7.350000e+002 7.200000e+002 7.060000e+002 6.930000e+002 6.820000e+002 6.720000e+002 6.650000e+002 6.590000e+002
1.085000e+003 1.160000e+003 1.166000e+003 1.176000e+003 1.192000e+003 1.211000e+003 1.234000e+003 1.261000e+003 1.289000e+003 1.947000e+003

Remember, the last 4 columns of this data would be duplicated. So total of 14 columns will be in the final answer.

Again thanks for helping me out.
 

{ for ( x = 0 ; x < NF ; x ++ )
{
printf("%s ",$x);
}

y = NF - 4;
if ( y < 0 )
{
y = 0;
}
for ( x = y ; x < NF ; x ++ )
{
printf("%s ",$x);
}

printf("\n");

}


I haven't run this so I might have an off by 1 error where it will only print the last 3 fields or maybe fields 5 - 1 instead of 4 - 0.

Also the if statement just validates there are at least 4 fields.

----
 

Sorry. I didn't allow for more than one space between fields. This version works with any number of spaces or tabs between fields.

Code:
BEGIN{ f = "[ \t]+[^ \t]+"; lastfour = f f f f "$" }

{ sub( lastfour, "&&" )
  print
}
 
futurelet:

That's a nice solution. Could you pleast explain how it works?

Regards,


Ed
 
Not as compact as futurelet's, but works with the data you posted:
Code:
BEGIN {n = 4}
{
    for (i=0; i<n; i++) {
        a[i+1]=$(NF - i)
    }
    printf("%s%s", $0, OFS)
    for (j=n; j>=1; j--) {
        printf("%s%s", a[j], (j > 1)? OFS: "\n")
    }
}
 

[tt]
BEGIN{ f = "[ \t]+[^ \t]+"; lastfour = f f f f "$" }
[/tt]
To make Awk execute some code before it starts reading the files listed
on the command line, enclose it in [tt]BEGIN{ ... }[/tt].
We want to build a regular expression that will match the last 4 fields.
To save typing, we use the variable [tt]f[/tt] to hold the pattern for
one field and its preceding whitespace. [tt][ \t][/tt] is a character
class that will match either a space or a tab. The following [tt]+[/tt]
means to match the preceding item at least once and as many times as
possible. The leading [tt]^[/tt] in [tt][^ \t][/tt] means match any
character except a space or a tab. Since [tt]lastfour[/tt] ends
with [tt]$[/tt], it will match only at the very end of the data string.
[tt]
sub( lastfour, "&&" )
[/tt]
Where the regular expression [tt]lastfour[/tt] is found, substitute
[tt]"&&"[/tt]. Since Awk wasn't given a variable upon which to perform
the substitution, it does it to [tt]$0[/tt], which is the record just
read. In Awk, an [tt]&[/tt] in the replacement string represents the
substring that was matched by the regular expression. Example:
[tt]
BEGIN {
$0 = "the cart or the horse"
gsub( /cart|horse/, "-&-" ) # gsub() does multiple substitutions.
print
}

the -cart- or the -horse-
[/tt]
If we want to replace with a literal [tt]-&-[/tt]:
[tt]
gsub( /cart|horse/, "-\\&-" )
[/tt]
Finally,
[tt]print[/tt]
prints [tt]$0[/tt] by default, since nothing was given it to print.

 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top