switch values

Hi all,

I am a relative novice with awk and am stuck on something I can't help
thinking ought to be really simple. I have a file "mydata.txt" as
below

x  20    x   20 x
 x  45    x   45  x
 x  100  x  100 x
 x  50    x   50  x

I am trying to write a simple script that will output the following
from this file

x  20    x   45 x
 x  45    x   20  x
 x  100  x  50 x
 x  50    x   100  x
 

I just can't seem to do this, but it must be really simple?
Thanks

Try:

awk 'NR%2{x=$2}!NR%2{$2=x;print;$2=$4;$4=x;print}' mydata.txt
1 Like
awk -F'x' '{a=$2;printf FS $2 FS;getline;printf $3"\n" FS $3 FS a"\n";}' mydata.txt
1 Like
nawk 'BEGIN{ARGV[ARGC++]=ARGV[1]} FNR==NR{a[FNR]=$(NF-1);next}{$(NF-1)=(FNR%2)?a[FNR+1]:a[FNR-1]}1' myFile
1 Like

Thanks vgersh99
Its working, can you tell me which part to change , in case 2 numbers are in different columns ( not 2 and 4)?
Thanks

to swap columns 4 - adjust as needed.

nawk -v c=4 'BEGIN{ARGV[ARGC++]=ARGV[1]} FNR==NR{a[FNR]=$c;next}{$c=(FNR%2)?a[FNR+1]:a[FNR-1]}1' myFile
1 Like

Hi,

In reality my file has thousand of rows and columns.
It would be nice to set explicitly which 2 columns to swap. They can appeare same values in different places, so I should be able to swap values just only on the column positions.
For example in this case:

x  20   x  y 20 x
x  45   x  y  45  x
x  100  x  y 100  x
x  50   x  y  50  x
x  70  x y 70 x
x  80  x y 80 x

I want to swap values on column 2 and column5 so I will receive:

x  20   x  y 45  x
x  45   x  y  20  x
x  100  x  y 50  x
x  50   x  y  100  x
x  70  x y 80 x
x  80  x y 70 x

Thanks

I don't follow your sample.
Given your latest sample and

nawk -v c=5 'BEGIN{ARGV[ARGC++]=ARGV[1]} FNR==NR{a[FNR]=$c;next}{$c=(FNR%2)?a[FNR+1]:a[FNR-1]}1' yourLatestSample

produces:

x 20 x y 45 x
x 45 x y 20 x
x 100 x y 50 x
x 50 x y 100 x
x 70 x y 80 x
x 80 x y 70 x

anything wrong with that?

1 Like

Hi Vgersh99,

Sorry but your code seems to be working just for my sample file, here is the original file.
I need the spaces between columns, they are important for further parsing.
Thanks

INPUT:

TT0006033250                         20110524-07:01:46  GNAGL22            TT   GNAGL22            
TT0006033250                         20110524-07:01:46  BRTPAS44            TT   BRTPAS44            
XX0000120172                        20110524-07:02:08  SORTH21           GG  SORTH21            
XX0000120172                        20110524-07:02:08  TQKUT99          GG  TQKUT99

OUTPUT:

TT0006033250                         20110524-07:01:46  GNAGL22            TT   BRTPAS44            
TT0006033250                         20110524-07:01:46  BRTPAS44            TT   GNAGL22            
XX0000120172                        20110524-07:02:08  SORTH21           GG  TQKUT99            
XX0000120172                        20110524-07:02:08  TQKUT99          GG  SORTH21

---------- Post updated at 07:24 AM ---------- Previous update was at 06:27 AM ----------

Please check, thanks

assuming all the fields are of the constant width....

nawk -v c=5 '
BEGIN {
   ARGV[ARGC++]=ARGV[1]
}
FNR==NR && NR==1 {
  copy0=$0
  for(i=1;i<=NF;i++){
    match(copy0, FS FS "*")
    fw=RSTART+RLENGTH
    copy0=substr(copy0,RSTART+RLENGTH)
  }
}
FNR==NR{
    a[FNR]=$c
    next
}
{
$c=(FNR%2)?a[FNR+1]:a[FNR-1]
for(i=1;i<=NF;i++)
  printf("%-*s%c", fw, $i,(i==NF)?ORS:"")
}' yourLatestSample
1 Like

You can also try this:

perl -ane 'if ($.%2){$x=$_;$y=$F[2]};if ($.%2==0) {$x=~s/(([^\s]+\s+){4})\w+/\1$F[4]/;print $x;s/(([^\s]+\s+){4})\w+/\1$y/;print}' mydata.txt
1 Like

Hi Bartus ,
Thanks your code seems to be working.
Just one question where can I set columns , which should swap, because
those could change in different files.

perl -anse 'BEGIN{$c--};if ($.%2){$x=$_;$y=$F[$c]};if ($.%2==0) {$x=~s/(([^\s]+\s+){$c})\w+/\1$F[$c]/;print $x;s/(([^\s]+\s+){$c})\w+/\1$y/;print}' -- -c=5 mydata.txt

c=5 means 5th column.

1 Like

Thanks Bartus
Works perfectly

awk '{
if(NR%2==1)
{
  a=sprintf("%s %s %s",$1,$2,$3)
  b=sprintf("%s %s %s",$4,$5,$6)
}
else{
  print a" "$4" "$5" "$6
  print $1" "$2" "$3" "b
}
}' yourfile 
1 Like

Hi Bartus,

Your code is working ALMOST correct expect this :
As you can see in case if one of values in 3rd columns is longer/shorter output has last column ('TWT') starting on different position , which is not acceptable for me, all fields should start at the same position.
One solution would be possibility to set column - start position.
Thanks a lot for replies

INPUT:

TT0006033250                     20110524-07:01:46  GNAGL22             TT  GNAGL22           TWT
TT0006033250                     20110524-07:01:46  GNAGL22ZZ           TT  GNAGL22ZZ         TWT
TT0000120172                     20110524-07:02:08  SORTH21             GG  SORTH21           TWT
TT0000120172                     20110524-07:02:08  TQKUT99             GG  TQKUT99           TWT

OUTPUT:

TT0006033250                     20110524-07:01:46  GNAGL22             TT  GNAGL22ZZ           TWT
TT0006033250                     20110524-07:01:46  GNAGL22ZZ           TT  GNAGL22           TWT
TT0000120172                     20110524-07:02:08  SORTH21             GG  TQKUT99           TWT
TT0000120172                     20110524-07:02:08  TQKUT99             GG  SORTH21           TWT

---------- Post updated at 08:34 AM ---------- Previous update was at 07:05 AM ----------

Hi Bartus,
Please check it , your code is the only one working :slight_smile:
Thanks

Try:

perl -nse 'BEGIN{$c--};if ($.%2){$x=$_;/([^\s]+\s+){$c}(\w+\s+)/;$y=$2};if ($.%2==0) {/([^\s]+\s+){$c}(\w+\s+)/;$z=$2;$x=~s/(([^\s]+\s+){$c})\w+\s+/\1$z/;print $x;s/(([^\s]+\s+){$c})\w+\s+/\1$y/;print}' -- -c=5 mydata.txt

PS: I feel bad for anyone supporting this code in the future :stuck_out_tongue:

Thanks Barturs