ericj
ericj

Reputation: 2291

When columns are seperated by multiple spaces, how to change a column and keep the spaces?

I have a file where the columns are seperated by multiple spaces.

How can I set, let's say, the second column, and keep the spaces on the line?

For example, in postgres' pg_hba.conf there is a line

local  all   all          peer

How can I change 'peer' to 'trust' and keep the spaces as they are on the line? When I let awk do $4="trust" there will be one space between the columns. In principle that is OK, but it makes the file harder to read, because of the position of headers above the line in the file.

Upvotes: 1

Views: 231

Answers (3)

Ed Morton
Ed Morton

Reputation: 203169

You need to use a regexp and operate on the whole record by specifying how many initial fields (\S+) plus separators (\s+) to skip before making your change, e.g. with GNU awk for gensub() and \s/\S:

$ awk '{$0=gensub(/(\s*(\S+\s+){3})\S+/,"\\1trust",1)}1' file
local  all   all          trust

Changing field 3 is a harder/better test of any potential solution since it's contents (all) appear earlier in the line too:

$ awk '{$0=gensub(/(\s*(\S+\s+){2})\S+/,"\\1trust",1)}1' file
local  all   trust          peer

The regexp starts with \s* since by default awk ignores leading white space but that's not actually needed for your specific data.

With other awks you'd do:

$ awk 'match($0,/[[:space:]]*([^[:space:]]+[[:space:]]+){2}/) {
    head = substr($0,1,RLENGTH)
    tail = substr($0,RLENGTH+1)
    sub(/[^[:space:]]+/,"trust",tail)
    print head tail
}' file
local  all   trust          peer

Upvotes: 1

karakfa
karakfa

Reputation: 67467

here is one approach

$ echo "local  all   all          peer" | 
  awk 'gsub("peer","trust")'

local  all   all          trust

here is another approach if you're changing the field not by value but by index. For example change third field to "trust" this time

$ echo "local  all   all          peer" | 
  awk -v RS='[^ ]+' -v ORS="" '{print $0 (NR==3?"trust":RT)}'

local  all   trust          peer

Upvotes: 1

James Brown
James Brown

Reputation: 37394

You really can't. If the amount of space varies between fields. Changing a field value will lead to rebuilding the record which means that the field separator FS is replaced by output field separator OFS.

You can try your luck with regex, though.

Upvotes: 0

Related Questions