Awk 当列被多个空格分隔时,如何更改列并保留空格?

Awk 当列被多个空格分隔时,如何更改列并保留空格?,awk,Awk,我有一个文件,其中列由多个空格分隔 比如说,我如何设置第二列,并保持空格在同一行 例如,在postgres的pg_hba.conf中有一行 local all all peer 如何将“对等”更改为“信任”,并保持空间在线?当我让awk执行$4=“trust”时,列之间将有一个空格。原则上这是可以的,但这会使文件更难读取,因为文件中标题的位置在行的上方。你真的不能。如果字段之间的空间大小不同。更改字段值将导致重建记录,这意味着字段分隔符FS将替换为输出字段分隔符OFS

我有一个文件,其中列由多个空格分隔

比如说,我如何设置第二列,并保持空格在同一行

例如,在postgres的pg_hba.conf中有一行

local  all   all          peer

如何将“对等”更改为“信任”,并保持空间在线?当我让awk执行
$4=“trust”
时,列之间将有一个空格。原则上这是可以的,但这会使文件更难读取,因为文件中标题的位置在行的上方。

你真的不能。如果字段之间的空间大小不同。更改字段值将导致重建记录,这意味着字段分隔符
FS
将替换为输出字段分隔符
OFS

不过,您可以用正则表达式试试运气。

这里有一种方法

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

local  all   all          trust
如果不是按值而是按索引更改字段,那么这里有另一种方法。例如,这次将第三个字段更改为“信任”

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

local  all   trust          peer

您需要使用regexp并通过指定在进行更改之前要跳过的初始字段(
\S+
)和分隔符(
\S+
)的数量对整个记录进行操作,例如使用GNU awk for gensub()和
\S
/
\S

$ awk '{$0=gensub(/(\s*(\S+\s+){3})\S+/,"\\1trust",1)}1' file
local  all   all          trust
更改字段3是对任何潜在解决方案的更难/更好的测试,因为它的内容(
all
)也出现在行的前面:

$ awk '{$0=gensub(/(\s*(\S+\s+){2})\S+/,"\\1trust",1)}1' file
local  all   trust          peer
regexp以
\s*
开头,因为默认情况下,awk忽略前导空格,但您的特定数据实际上不需要前导空格

对于其他AWK,您可以执行以下操作:

$ 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

你能举个例子来说明你在找什么吗?使用
-F'\t'
作为列分隔符,并使用
$2=…
设置第二列。很抱歉,我看到这些列被多个空格分隔。但也许这并不重要。文件是postgres'pg_hba.conf,其中一行看起来像:
local all peer
,如何将'peer'设置为'trust'并保持空间不变?列之间的空格数是不同的,但stackoverflow没有显示出来。当我让awk to
$4=trust
时,两列之间的所有空格都会折叠成一个空格。嘿,ericj,试着在帖子中提供这些细节。它提高了对问题的理解。gawk-4.1.0:awk-v FS=“\t+”{print;printf(“[1]=%s,[2]=%s,[3]=%s\n',$1,$2,$3”);}如果不这样做,当
“peer”
作为前面某列的一部分出现时,它将失败。尝试用这种方法将字段3(
all
)替换为
trust
。您应该提到第二种解决方案是特定于gawk的。另外,它只在只有一行输入时有效,如果字段之间有制表符则无效,如果替换第四个字段,则不会在输出末尾打印换行符。