Print all other variables in awk
I'm trying to write a quick awk script that converts strings in this format:
AAAA BBBB CCCC DDDD...
to
CCCC AAAA BBBB DDDD...
This is my script:
{ printf "%s %s %s %s", $3, $1, $2, $4 };
This works great except when the original input line has more than 4 tokens, in which case the fifth and subsequent tokens are not printed.
I have checked several answers, such as Using awk to print all columns from nth to last , but they rely on setting variables to ""
, which seem to cause problems if these variables are reused later.
Is there an easy way to replace $4
it with something like "substring from $ 4 to end of string"?
source to share
In this simple case, you only need:
$ awk '{t=$3; $3=$2; $2=$1; $1=t}1' file
CCCC AAAA BBBB DDDD
but in general with GNU awk for gensub()
, \s
and \s
:
$ awk '{print $3, $1, $2, gensub(/^\s*(\S+\s+){3}/,"","")}' file
CCCC AAAA BBBB DDDD
gensub()
just skips the first 3 fields and will leave all margins and spaces between fields as-from this point:
$ cat file
AAAA BBBB CCCC DDDD EEEE FFFF GGGG
$ awk '{print $3, $1, $2, gensub(/^\s*(\S+\s+){3}/,"","")}' file
CCCC AAAA BBBB DDDD EEEE FFFF GGGG
With other awks, you can do the same with match()+substr()
:
$ awk '{match($0,/^[[:space:]]*([^[:space:]]+[[:space:]]+){3}/); print $3, $1, $2, substr($0,RLENGTH+1)}' file
CCCC AAAA BBBB DDDD EEEE FFFF GGGG
or sub()
and a variable:
$ awk '{x=$0; sub(/^[[:space:]]*([^[:space:]]+[[:space:]]+){3}/,"",x); print $3, $1, $2, x}' file
CCCC AAAA BBBB DDDD EEEE FFFF GGGG
source to share
It's not necessarily "easy", but it's not that hard:
{ printf "%s %s %s ", $3, $1, $2;
for (i=4; i<= NF; ++i) {
printf "%s ", $i;
}
printf "\n";
}
Another way, a little smarter:
{ N3 = $3; N2 = $2; N1 = $1; // capture the fields
$1 = N3; $2 = N1; $3 = N2; // reorder the fields
print; // print the whole record
}
source to share