swapping Easting and Northing coordinates

Pat Morrow pmorrow at maildrop.srv.ualberta.ca
Fri Mar 29 07:00:00 EST 1996

Recently, someone posted an inquiry to the GRASS user newsgroup (and
mailing list as well?) about how to swap columns of information
(Easting and Northing).  A couple of responses using the language awk
were posted.  While these 3 statement programs were succinct, they
might leave a little to be desired in terms of general usefulness :-)

I have written a program in perl, which can extract a given column from
a stream of text (including a file), rearrange the columns of
information, extract specific columns in a specific order, and
optionally keep information from a certain column to the end of line.
To be of more usefulness to the GRASS community, this program will
optionally ignore or print the first N lines of a file.

If a line of text does not contain enough lines of information in
order to be successfully printed in the requested order, the program
by default ignores the line (effectively deleting it).  There is a
command line switch which causes the program to echo the line, as is,
to the output.

The program is set up such that it will examine the command line for
non-switches.  These non-switches are assumed to be column numbers if
numeric,and a (single) input file name if non-numeric.  Without a file
specified on the command line to read from, the program reads from
standard input.  Program output is directed to standard output; error
messages to the standard error stream.  This behavior allows the
program to be used in UNIX pipes for processing data.

If the program does not perform fast enough for you (perl is sort of
an interpreted language), it should not be too difficult to translate
the program into C.

Usage: swap_col [-d X] [-[ip] N] [-D] [-k] N1 [N2 ...] [file]

The -d X switch changes the column delimiter character from one or
more whitespace characters (spaces or tabs) to the character X.  (This
has not been exhaustively tested, but it does work for a number of
``magic'' characters, such as the pipe symbol).

Either the -i or the -p switch can be given, along with a number.
This will cause the program to ignore or print the first N lines of
the input text stream.

The -D switch causes swap_col to print a line as is that does not have
enough columns of information to split properly.

The -k switch, along with the presence of the last column number being
the largest, causes swap_col to print out all the columns of
information, for every line.

If one column is separated from another by more than one column
delimiter, on output only ONE delimiter is used.

I hope the above is useful.  It should work with perl versions 3 to 5,
although it does depend on the getopts.pl library routine.  If your
perl implementation does not have getopts.pl, it should not be too
difficult to parse @ARGV manually.  Bug reports welcome
(ghaverla at freenet.edmonton.ab.ca), flames to /dev/null.

Gordon Haverland, P.Eng.
Precision Farming Project
Alberta Agriculture, Food and Rural Development
Conservation and Development Branch


# swap_col [-d X] [-[ip] N] [-k] [-D] N1 [N2 N3 ...] [file]

# This program can be used to swap or extract arbitrary columns of
# information from a text stream or file.  The columns of information
# are assumed to be delimited by default by one or more characters
# of whitespace.  The user can change the column delimiter to
# some other character by means of the -d X flag.  If a user wants
# to keep everything from the M'th column to the end of line, then
# specifying the number M as the last number, and setting the -k
# flag will result in keeping all that information.  By default this
# program reads from the standard input (allowing pipes to process
# information).  Output is written to the standard output.  If the
# user wants to keep the information in a file, the standard output
# should be redirected to a file.  Some files of information have
# a header portion.  The first N lines can be ignored or printed by
# setting either the -i or -p switches.

# Program peculiarities:  if a line of information does not have
# enough columns of information to make swapping possible, the
# program will silently ignore the line.  This effectively deletes
# that line from the data stream.  Specifying the -D flag
# will cause the line to be copied as is to the output.  While it
# is possible to have a filename such as "1" under many operating
# systems, this program assumes a "1" on the command line is a
# request to print the first column.

require "getopts.pl";

# Call Getopts() to process command line for flags
&Getopts('d:i:p:hkD');          # -k  keep info in later columns if last
                                #     column number is largest present.
                                # -h  print usage message.
                                # -D  Don't delete lines with 
                                #     columns of information.
                                # -i N  ignore first N lines
                                # -p N  print first N lines as is

if( $opt_h ) {
    &usage();    # No return from here
if( $opt_i && $opt_p ) {

# Process remaining command line.  Should only be output numbers and 
# an input file name.
$max_N = -1;
$out_cols = 0;
$file = "stdin";
for( $i = 0; $i <= $#ARGV; $i++ ) {
    if( $ARGV[$i] =~ /^\d+$/ ) { # digits only, must be a column number
        ($ARGV[$i] > 0) ||
                die "Error, can't print out a column number less than 

        # Increment number of output_columns (0 = no columns)

        # save this column number, but convert to zero origin array
        $col[$out_cols] = $ARGV[$i] - 1;

        # Is this the largest column number index seen????
        if( $col[$out_cols] > $max_N ) {
            $max_N = $col[$out_cols]; # Yes!  Save it.
    } else {                    # ARGV is a filename (hopefully)
        $file = $ARGV[$i];
        open( INPUT, "< $ARGV[$i]" ) ||
            die "Error, cannot open $ARGV[$i] as input.\n";

if( ($col[$out_cols] == $max_N) && ($opt_k) ) {
    $keep = 1;

if( $file eq "stdin" ) {
    open( INPUT, "-" ) || die "Error, can't open stdin!!\n";

if( $out_cols == 0 ) {
    die "No information to extract and output.  Quitting.\n";

# Set up the perl regular expression for splitting the input
if( $opt_d ) {
    if( $opt_d =~ /[|^+\$\[({\\})\]]/ ) {
        $split_pat = "\\";
        $split_pat .= $opt_d;
    } else {
     $split_pat = $opt_d;
 $split_pat .= "+";
} else {
 $split_pat = "[ \t]+";

# And the output column delimiter
if( $opt_d ) {
    $outchar = $opt_d;
} else {
 $outchar = " ";

if( $opt_i || $opt_p ) {
    if( $opt_i ) {
        $n = $opt_i;
    } else {
     $n = $opt_p;

    for( $i = 0; $i < $n; $i++ ) {
        $junk = <INPUT>;
        if( $opt_p ) {
            print "$junk";

# Okay, process the input
while( <INPUT> ) {
    chop( $_ );                 # Remove the newline (return) from EOL

    # Split input into column entries
    @a = split( /$split_pat/o );

    # Is there enough columns of information in this row to swap??
    if( $#a < ($max_N-1) ) {  # No, not enough columns
        if( $opt_D ) {
            print "$_\n";

    } else {                  # yes there is enough columns
        # Okay, swap the columns around
        print "$a[$col[1]]";
        for( $i = 2; $i <= $out_cols; $i++ ) {
            printf "%1s%s", $outchar, $a[$col[$i]];

        # Does the user want to $keep trailing information???
        if( $keep ) {
            for( $i = $max_N+1; $i <= $#a; $i++ ) {
                printf "%1s%s", $outchar, $a[$i];

    # Spit out a newline to end this line of output
    print "\n";

sub usage {
  print STDERR "Usage: swap_col [-d X] [-[ip] N] [-k] [-D] N1 [N2 N3] 
  print STDERR "       where -d X indicates that you wish to change the 
  print STDERR "       delimiter to X\n";
  print STDERR "       -[ip] N indicates that you would like the first 
the first\n";
  print STDERR "       N lines of the file ignored or passed without 
  print STDERR "       -k indicates that you wish to keep trailing 
  print STDERR "       -D indicates you want lines of input with 
  print STDERR "       columns to be copied to the output\n";
  print STDERR "       N1 is the index of the first column you want to 
  print STDERR "       N2 is the index of the second column, ...\n";
  print STDERR "       and file is an optional filename for input\n";

More information about the grass-user mailing list