How to sort array

  • Follow


Hi All
How to using sort in awk ?

try   printf("%s\n",a[ele])  | "sort" is not good.


#!/bin/ksh
# 2008/12/11
  echo "" |  awk '{
    a[2] = "d  1"
    a[0] = "9  2"
    a[1] = "8  3"
  for (ele in a) {
     printf("%s\n",a[ele])
  }
 }'


d  1
9  2
8  3

want

8  3
9  2
d  1





0
Reply moonhkt 12/11/2008 9:30:01 AM

On Thu, 11 Dec 2008 01:30:01 -0800 (PST), moonhkt <moonhkt@gmail.com> wrote:

>Hi All
>How to using sort in awk ?
>
>try   printf("%s\n",a[ele])  | "sort" is not good.
>
>
>#!/bin/ksh
># 2008/12/11
>  echo "" |  awk '{
>    a[2] = "d  1"
>    a[0] = "9  2"
>    a[1] = "8  3"
>  for (ele in a) {
>     printf("%s\n",a[ele])
>  }
> }'
>
>
>d  1
>9  2
>8  3
>
>want
>
>8  3
>9  2
>d  1
>
$ awk 'BEGIN{ a[2] = "d  1"; a[0] = "9  2"; a[1] = "8  3"; \
	n = asort(a, sorted); for (i = 1; i <= n; i++) print sorted[i] }'


8  3
9  2
d  1

Grant.
-- 
http://bugsplatter.id.au
0
Reply Grant 12/11/2008 12:18:56 PM


Grant wrote:

> On Thu, 11 Dec 2008 01:30:01 -0800 (PST), moonhkt <moonhkt@gmail.com> wrote:
> 
>> Hi All
>> How to using sort in awk ?
> $ awk 'BEGIN{ a[2] = "d  1"; a[0] = "9  2"; a[1] = "8  3"; \
> 	n = asort(a, sorted); for (i = 1; i <= n; i++) print sorted[i] }'
> 
> 
> 8  3
> 9  2
> d  1

Note that asort() requires GNU awk. With other awk implementation, a way to
get an array sorted is to do

awk 'BEGIN{ a[2] = "d  1"; a[0] = "9  2"; a[1] = "8  3";
 	for(i in a)print a[i] | "sort"}'

or, if the data must be reused later, write it to a temp file and read it
back in an array:

awk 'BEGIN{ a[2] = "d  1"; a[0] = "9  2"; a[1] = "8  3";
 	for(i in a)print a[i] | "sort > tmpfile";
        close("sort > tmpfile");
        while(getline a[++n] < "tmpfile");
         for(i=1;i<=n;i++)print a[i]
}'

(I don't think that can be done without a temp file unless coprocesses are
used, which are another gawk extension, but corrections welcome)

-- 
awk 'BEGIN{O="~"~"~";o="=="=="==";o+=+o;x=O""O;while(X++<=x+o+o)c=c"%c";
printf c,(x-O)*(x-O),x*(x-o)-o,x*(x-O)+x-O-o,+x*(x-O)-x+o,X*(o*o+O)+x-O,
X*(X-x)-o*o,(x+X)*o*o+o,x*(X-x)-O-O,x-O+(O+o+X+x)*(o+O),X*X-X*(x-O)-x+O,
O+X*(o*(o+O)+O),+x+O+X*o,x*(x-o),(o+X+x)*o*o-(x-O-O),O+(X-x)*(X+O),x-O}'
0
Reply Dave 12/11/2008 10:06:05 PM

On 12$B7n(B12$BF|(B, $B>e8a(B6$B;~(B06$BJ,(B, Dave B <da...@addr.invalid> wrote:
> Grant wrote:
> > On Thu, 11 Dec 2008 01:30:01 -0800 (PST), moonhkt <moon...@gmail.com> wrote:
>
> >> Hi All
> >> How to using sort in awk ?
> > $ awk 'BEGIN{ a[2] = "d  1"; a[0] = "9  2"; a[1] = "8  3"; \
> >    n = asort(a, sorted); for (i = 1; i <= n; i++) print sorted[i] }'
>
> > 8  3
> > 9  2
> > d  1
>
> Note that asort() requires GNU awk. With other awk implementation, a way to
> get an array sorted is to do
>
> awk 'BEGIN{ a[2] = "d  1"; a[0] = "9  2"; a[1] = "8  3";
>         for(i in a)print a[i] | "sort"}'
>
> or, if the data must be reused later, write it to a temp file and read it
> back in an array:
>
> awk 'BEGIN{ a[2] = "d  1"; a[0] = "9  2"; a[1] = "8  3";
>         for(i in a)print a[i] | "sort > tmpfile";
>         close("sort > tmpfile");
>         while(getline a[++n] < "tmpfile");
>          for(i=1;i<=n;i++)print a[i]
>
> }'
>
> (I don't think that can be done without a temp file unless coprocesses are
> used, which are another gawk extension, but corrections welcome)
>
> --
> awk 'BEGIN{O="~"~"~";o="=="=="==";o+=+o;x=O""O;while(X++<=x+o+o)c=c"%c";
> printf c,(x-O)*(x-O),x*(x-o)-o,x*(x-O)+x-O-o,+x*(x-O)-x+o,X*(o*o+O)+x-O,
> X*(X-x)-o*o,(x+X)*o*o+o,x*(X-x)-O-O,x-O+(O+o+X+x)*(o+O),X*X-X*(x-O)-x+O,
> O+X*(o*(o+O)+O),+x+O+X*o,x*(x-o),(o+X+x)*o*o-(x-O-O),O+(X-x)*(X+O),x-O}'

Thank. Rewrite as below.

#!/bin/ksh
# 2008/12/11
  cp /dev/null  _abc.txt
  echo "" |  awk '{
    a[2] = "d  1"
    a[0] = "9  2"
    a[1] = "8  3"
  for (ele in a) {
     printf("%s\n",a[ele]) | "sort >> _abc.txt"   ;
  }
  close("sort >> _abc.txt");
  while(getline a[++n] < "_abc.txt");
   for(i=1;i<=n;i++)print a[i]
 }'


0
Reply moonhkt 12/12/2008 2:39:43 AM

moonhkt wrote:

> Thank. Rewrite as below.
> 
> #!/bin/ksh
> # 2008/12/11
>   cp /dev/null  _abc.txt
>   echo "" |  awk '{
>     a[2] = "d  1"
>     a[0] = "9  2"
>     a[1] = "8  3"
>   for (ele in a) {
>      printf("%s\n",a[ele]) | "sort >> _abc.txt"   ;
>   }
>   close("sort >> _abc.txt");
>   while(getline a[++n] < "_abc.txt");
>    for(i=1;i<=n;i++)print a[i]
>  }'

You don't need to do echo "" | awk ... (which, btw, is the same as echo |
awk ...). Just put your awk code in the BEGIN section and don't use the echo.

-- 
awk 'BEGIN{O="~"~"~";o="=="=="==";o+=+o;x=O""O;while(X++<=x+o+o)c=c"%c";
printf c,(x-O)*(x-O),x*(x-o)-o,x*(x-O)+x-O-o,+x*(x-O)-x+o,X*(o*o+O)+x-O,
X*(X-x)-o*o,(x+X)*o*o+o,x*(X-x)-O-O,x-O+(O+o+X+x)*(o+O),X*X-X*(x-O)-x+O,
O+X*(o*(o+O)+O),+x+O+X*o,x*(x-o),(o+X+x)*o*o-(x-O-O),O+(X-x)*(X+O),x-O}'
0
Reply Dave 12/12/2008 9:25:45 AM

On Dec 11, 8:39 pm, moonhkt <moon...@gmail.com> wrote:
> On 12$B7n(B12$BF|(B, $B>e8a(B6$B;~(B06$BJ,(B, Dave B <da...@addr.invalid> wrote:
>
>
>
>
>
> > Grant wrote:
> > > On Thu, 11 Dec 2008 01:30:01 -0800 (PST), moonhkt <moon...@gmail.com> wrote:
>
> > >> Hi All
> > >> How to using sort in awk ?
> > > $ awk 'BEGIN{ a[2] = "d  1"; a[0] = "9  2"; a[1] = "8  3"; \
> > >    n = asort(a, sorted); for (i = 1; i <= n; i++) print sorted[i] }'
>
> > > 8  3
> > > 9  2
> > > d  1
>
> > Note that asort() requires GNU awk. With other awk implementation, a way to
> > get an array sorted is to do
>
> > awk 'BEGIN{ a[2] = "d  1"; a[0] = "9  2"; a[1] = "8  3";
> >         for(i in a)print a[i] | "sort"}'
>
> > or, if the data must be reused later, write it to a temp file and read it
> > back in an array:
>
> > awk 'BEGIN{ a[2] = "d  1"; a[0] = "9  2"; a[1] = "8  3";
> >         for(i in a)print a[i] | "sort > tmpfile";
> >         close("sort > tmpfile");
> >         while(getline a[++n] < "tmpfile");
> >          for(i=1;i<=n;i++)print a[i]
>
> > }'
>
> > (I don't think that can be done without a temp file unless coprocesses are
> > used, which are another gawk extension, but corrections welcome)
>
> > --
> > awk 'BEGIN{O="~"~"~";o="=="=="==";o+=+o;x=O""O;while(X++<=x+o+o)c=c"%c";
> > printf c,(x-O)*(x-O),x*(x-o)-o,x*(x-O)+x-O-o,+x*(x-O)-x+o,X*(o*o+O)+x-O,
> > X*(X-x)-o*o,(x+X)*o*o+o,x*(X-x)-O-O,x-O+(O+o+X+x)*(o+O),X*X-X*(x-O)-x+O,
> > O+X*(o*(o+O)+O),+x+O+X*o,x*(x-o),(o+X+x)*o*o-(x-O-O),O+(X-x)*(X+O),x-O}'
>
> Thank. Rewrite as below.
>
> #!/bin/ksh
> # 2008/12/11
>   cp /dev/null  _abc.txt

The normal way to create an empty file is:

   > _abc.txt

>   echo "" |  awk '{

as Dave said, change that line to:

    awk 'BEGIN{

>     a[2] = "d  1"
>     a[0] = "9  2"
>     a[1] = "8  3"
>   for (ele in a) {
>      printf("%s\n",a[ele]) | "sort >> _abc.txt"   ;

printf is a builtin not a function, so adding "()" is misleading.
Also, 'printf "%s\n",string' is the same as 'print string' so there's
no need for printf so that can be just:

       print a[ele] | ...

When invoking an external command, since you need to close exactly the
same string you're opening, use a variable instead of specifying the
same string twice to make sure you do close it:

      cmd = "sort >> _abc.txt"
      print a[ele] | cmd

>   }
>   close("sort >> _abc.txt");

    close(cmd)

>   while(getline a[++n] < "_abc.txt");

The above doesn't do quite what you think it does in all cases. To be
safe, you'd have to change it to:

    while ( (getline a[++n] < "_abc.txt") > 0)

and make sure you read and understand http://tinyurl.com/yn9ka9 if
you're considering using getline.

Also, remember to close the file once you've read from it:

    close("_abc.txt")

>    for(i=1;i<=n;i++)print a[i]
>  }'

You probably want to add some protections around that, get rid of the
spurious semicolons, use a variable as the tmp file name instead of
having to specify the same thing everywhere, and remove the tmp file
when you're done too, e.g. (untested):

  tmp="abc$$.txt"
  > "$tmp" &&
  awk -v tmp="$tmp" 'BEGIN{
    a[2] = "d  1"
    a[0] = "9  2"
    a[1] = "8  3"
  cmd = "sort >> " tmp
  for (ele in a) {
     print a[ele]) | cmd
  }
  close(cmd);
  while( (getline a[++n] < tmp) > 0 )
     ;
  close(tmp)
  for(i=1;i<=n;i++)
      print a[i]
 }' &&
 rm -- "$tmp"

    Ed.

0
Reply Ed 12/14/2008 4:42:42 PM

(I'm replying to you since many of your comments are about the code I posted
originally)

Ed Morton wrote:

> When invoking an external command, since you need to close exactly the
> same string you're opening, use a variable instead of specifying the
> same string twice to make sure you do close it:
> 
>       cmd = "sort >> _abc.txt"
>       print a[ele] | cmd
> 
>>   }
>>   close("sort >> _abc.txt");
> 
>     close(cmd)

Fair enough, I just didn't think it was necessary since the command had to
be used only twice in the program (three times with the close(), ok, but
again that did not seem necessary to me for such a short program which does
only that and certainly does not run the risk of running out of available
file descriptors, at least as it's currently written).
Anyway, it's true that getting into the good habit costs nothing, so it's
better to do things correctly anyway.

>>   while(getline a[++n] < "_abc.txt");
> 
> The above doesn't do quite what you think it does in all cases. To be
> safe, you'd have to change it to:
> 
>     while ( (getline a[++n] < "_abc.txt") > 0)

Checking the return value of getline is better, thanks, although in this
case I implicitly assumed it could not produce an error, but again, your
code is admittedly more robust and just few keystrokes longer.

> and make sure you read and understand http://tinyurl.com/yn9ka9 if
> you're considering using getline.

Agreed, although I don't see how else you could read the contents of the
file into the array in this case without using getline.

Thanks for the remarks.

-- 
awk 'BEGIN{O="~"~"~";o="=="=="==";o+=+o;x=O""O;while(X++<=x+o+o)c=c"%c";
printf c,(x-O)*(x-O),x*(x-o)-o,x*(x-O)+x-O-o,+x*(x-O)-x+o,X*(o*o+O)+x-O,
X*(X-x)-o*o,(x+X)*o*o+o,x*(X-x)-O-O,x-O+(O+o+X+x)*(o+O),X*X-X*(x-O)-x+O,
O+X*(o*(o+O)+O),+x+O+X*o,x*(x-o),(o+X+x)*o*o-(x-O-O),O+(X-x)*(X+O),x-O}'
0
Reply Dave 12/14/2008 5:20:33 PM

On Dec 14, 11:20=A0am, Dave B <da...@addr.invalid> wrote:
> (I'm replying to you since many of your comments are about the code I pos=
ted
> originally)
>
> Ed Morton wrote:
> > When invoking an external command, since you need to close exactly the
> > same string you're opening, use a variable instead of specifying the
> > same string twice to make sure you do close it:
>
> > =A0 =A0 =A0 cmd =3D "sort >> _abc.txt"
> > =A0 =A0 =A0 print a[ele] | cmd
>
> >> =A0 }
> >> =A0 close("sort >> _abc.txt");
>
> > =A0 =A0 close(cmd)
>
> Fair enough, I just didn't think it was necessary since the command had t=
o
> be used only twice in the program (three times with the close(), ok, but
> again that did not seem necessary to me for such a short program which do=
es
> only that and certainly does not run the risk of running out of available
> file descriptors, at least as it's currently written).
> Anyway, it's true that getting into the good habit costs nothing, so it's
> better to do things correctly anyway.
>
> >> =A0 while(getline a[++n] < "_abc.txt");
>
> > The above doesn't do quite what you think it does in all cases. To be
> > safe, you'd have to change it to:
>
> > =A0 =A0 while ( (getline a[++n] < "_abc.txt") > 0)
>
> Checking the return value of getline is better, thanks, although in this
> case I implicitly assumed it could not produce an error, but again, your
> code is admittedly more robust and just few keystrokes longer.
>
> > and make sure you read and understandhttp://tinyurl.com/yn9ka9if
> > you're considering using getline.
>
> Agreed, although I don't see how else you could read the contents of the
> file into the array in this case without using getline.

getline might be fine for this, I'm just suggesting the OP be familiar
with it if he's going to usee it. Having said that, since the OP is
really writing a shell script and just using awk for parts of it, I'd
have found this:

   shell{ awk{} | sort{} | awk{} }

more natural than:

   shell{ awk{ shell{ sort{} }; getline }

i.e. something like this (again untested):

  awk 'BEGIN{
    a[2] =3D "d  1"
    a[0] =3D "9  2"
    a[1] =3D "8  3"
    for (i in a)
      print a[i]
  }' |
  sort |
  awk '{
    for(i=3D1;i<=3DNF;i++) {
      a[i]=3D$i
      print a[i]
    }
  }'

and it wouldn't need a tmp file but no big deal either way.

   Ed.
0
Reply Ed 12/14/2008 11:14:27 PM

7 Replies
272 Views

(page loaded in 0.064 seconds)

Similiar Articles:













7/19/2012 10:41:12 PM


Reply: