Why does this awk script that runs on CentOS not run on Ubuntu?
As noted in the The GNU Awk User’s Guide
In many awk implementations, including gawk, the keyword
function
may be abbreviatedfunc
. (c.e.) However, POSIX only specifies the use of the keywordfunction
.
So the error is possibly because the implementation of awk
on your Ubuntu system is mawk
, or that something (such as a POSIXLY_CORRECT
environment variable) is affecting how gawk
behaves on your system.
Ubuntu used to ship with mawk
as the default awk
- but as far as I know, all currently supported versions use gawk
by default. If you installed mawk
via the packaqge management system, you should be able to use the update-alternatives
mechanism to query/set the default ex.
update-alternatives --query awk
sudo update-alternatives --config awk
isn't awk pretty much awk regardless of what machine you're on?
No, and you may even have multiple implementations on the same system. gawk
(GNU Awk) has a number of features not present in mawk
. The one you've run into isn't the only one. The gawk
documentation contains a list of common features that differ across major AWK implementations.
As steeldriver says, using func
as an abbreviation for function
is supported by some but not all AWK implementations. To solve this particular problem, the best thing to do is just change func
to function
. With that single change, your script works with mawk
as well as gawk
.
If for some reason you can't or don't wish to do that, or if you need other nonstandard functionality that gawk
provides but mawk
doesn't, you can use gawk
, which is provided by the gawk
package.
gawk -f loop.awk numbers.txt
As shown in steeldriver's answer, you can use update-alternatives
to make awk
resolve to gawk
rather than mawk
(or that may happen automatically when you install gawk
).
However, you're using awk -f
, so if you're willing to add a shebang line to the top of your AWK script and mark the script executable (chmod +x loop.awk
), then you can have it specify which interpreter ought to be used:
#!/usr/bin/awk -f
func printlist(n) {
for(i=1;i<=n;i++) {
printf("%d ",i)
}
printf("\n")
}
{printlist($1)}
You would then run the script with the command:
./loop.awk numbers.txt
Then other scripts remain unaffected.
For this tiny script with a single occurrence of the func
keyword that can be written as function
, adding a shebang probably isn't your best choice, unless you were going to do that anyway. For more complex situations where you need gawk
features not present in mawk
, though, I suggest considering it. Adding a shebang also has the benefit of clarifying what implementation of AWK you wish to be used, and a script for which this doesn't matter and that is written to be portable can have a #!/usr/bin/awk -f
shebang.
(Of course, scripts with such shebangs aren't totally portable in the broader sense, since they assume awk
is in /usr/bin
.)