Grail is quite correct. Here is a more complex solution, though.
When you have both spaces and tabs as field separators, and you'd prefer to keep them exactly as-is, you can use a regular expression to replace just the bit you want (using
gensub()). Here is an example for ChrisF682's case:
Code:
gawk '
BEGIN { RS="(\n|\r|\n\r|\r\n)"
FS="[\t\v\f ]+"
}
{ if ($3 ~ /^0[Xx]/)
value = strtonum($3)
else
value = strtonum("0x" $3)
line = $0
line = gensub(/([\t\v\f ]*)[^\t\v\f ]+/, "\\1" value, 3, line)
printf("%s%s", line, RT)
}
' input-file > output-file
I prefer to put setting the record (line) and field separators in a BEGIN rule; I think it is clearer this way. This one supports all newline conventions (Unix, old Mac, weird, and DOS, respectively). The field separator accepts any number of consecutive tabs, vertical tabs, formfeeds, and spaces as a single field separator. Although GNU awk supports character classes, they depend on the locale; I like to spell out exactly what I want.
The record rule starts very much like before. The decimal value of the third field is stored in variable
value.
The variable
line is initialized to contain the entire record (without the newline at end), exactly as gawk read it.
The
gensub() replaces the third match of (possible field separator and some field contents) with (the same field separator and the converted decimal value). Really, it does all the hard work here. If there is no third match, it changes nothing.
If you want to modify multiple fields at once, I intentionally wrote the scriptlet so that you can just duplicate (and modify) the gensub() line.
The printf line prints the possibly modified record, but also the same newline gawk saw,
RT. If you want the output to use Unix newlines, you can change the printf line to
printf("%s\n", line) instead.
To remind that this gawk scriptlet works on the third field of each input record (line), I bolded the
3's. If you were to change all four occurrences to say 1, it would work on the first field instead.
Note that the scriptlet assumes that if a record (line) begins with whitespace, that whitespace is just indentation. It does NOT mean that the first field is empty. However, this is just how awk normally works, so it should not be a surprise to anyone.
I hope you find this useful, or at least interesting.