koem
koem

Reputation: 574

bash: sort parts of a file

I have some "kind of SQL" files that I want to be partially sorted - to be able to compare them with each other later on.

CREATE TABLE BBBBBB
(
   ID bigint NOT NULL
   NAME varchar(50)
   CURRENCY varchar(3)
   SYS_START timestamp NOT NULL
   SYS_END timestamp NOT NULL
   TS_ID timestamp NOT NULL
   EXPORT int
)

CREATE TABLE AA
(
   ID bigint NOT NULL
   SYS_START timestamp NOT NULL
   SYS_END timestamp NOT NULL
   TS_ID timestamp NOT NULL
   NAME varchar(100) NOT NULL
)

I only want to have the parts inside the brackets sorted. The output shall be this:

CREATE TABLE BBBBBB
(
   CURRENCY varchar(3)
   EXPORT int
   ID bigint NOT NULL
   NAME varchar(50)
   SYS_END timestamp NOT NULL
   SYS_START timestamp NOT NULL
   TS_ID timestamp NOT NULL
)

CREATE TABLE AA
(
   ID bigint NOT NULL
   NAME varchar(100) NOT NULL
   SYS_END timestamp NOT NULL
   SYS_START timestamp NOT NULL
   TS_ID timestamp NOT NULL
)

I tried to put the parts in brackets into the sed hold buffer and sort them, but I didn't get far ... I don't have other ideas right now.

Upvotes: 2

Views: 447

Answers (4)

Juan Diego Godoy Robles
Juan Diego Godoy Robles

Reputation: 14955

Or gawk:

gawk 'BEGIN{PROCINFO["sorted_in"] = "@ind_str_asc"}
      /^\(/{f=1}
      /^\)/{f=0
            for (i in a)
              print a[i]
            delete a}
      f{a[$1]=$0}
      !f' yourfile

Check the ideone demo here.

From the docs

"@ind_str_asc" Order by indices in ascending order compared as strings; this is the most basic sort. (Internally, array indices are always strings, so with ‘a[2*5] = 1’ the index is "10" rather than numeric 10.)

Upvotes: 2

ma-ti
ma-ti

Reputation: 134

A solution using Vim:

vim -c ":/^(/+1,/^)/sort | /^(/-1 | /^(/+1,/^)/sort | wq" x.txt

Upvotes: 2

Arjun Mathew Dan
Arjun Mathew Dan

Reputation: 5298

With awk:

awk 'i {a[l++]=$0}
     /^\(/ {print; i=1}
     /^\)/ {n=asort(a); for(k=1; k<=n; k++){print a[k]} i=0; delete a; next}
     !i' File

Upvotes: 2

choroba
choroba

Reputation: 241898

Perl to the rescue!

perl -ne '
    $between = /^\(/ .. /^\)/;
    push @buff, $_ if $between && /^\s/;
    print "(\n", sort splice(@buff), ")\n" if $between =~ /E/;
    print unless $between
   ' -- file.sql
  • -n reads the input line by line
  • $between is true if you're between ( and ) at the beginning of a line.
  • lines starting with whitespace between parentheses are pushed to a buffer.
  • the buffer is sorted, printed, and emptied when the last line of the block is read.
  • other lines are printed directly.

Upvotes: 1

Related Questions