如何用awk保留第一个字段的前置空格并输出指定字段
保留字段原始前置空格输出指定字段的解决方案
问题描述
有如下格式的输入文本:
aaaaaa bbbb cccccc dddddddddddddd ee fff gggggggg hhh iiiii
需要仅输出第1和第3字段,同时保留第一个字段的原始前置空格,期望输出:
aaaaaa cccccc dddddddddddddd fff gggggggg iiiii
使用简单的print($1,$3)会丢失前置空格:
aaaaaa cccccc ddddddddddddddd fff gggggggg iiiii
尝试$1=sprintf("%20s",$1)会导致第一个字段右对齐到指定列,不符合需求:
aaaaaa cccccc dddddddddddddd fff gggggggg iiiii
解决方案
方法1:利用awk的match函数提取前置空格与字段内容
核心思路是先匹配每行开头的所有空白字符,再提取第一个非空白字段和第三个字段,最后拼接输出:
match($0, /^[[:space:]]+/, pre) { print pre[0] $1, $3 }
解释:
match($0, /^[[:space:]]+/, pre)匹配行首所有空白字符,存入数组prepre[0]就是行首的原始前置空格,再拼接$1和$3即可保留原始格式
方法2:拆分行首空白与内容,再重组
如果你的awk版本不支持第三个参数(存储匹配结果的数组),可以用以下写法:
{ space = substr($0, 1, length($0) - length(ltrim($0))) print space $1, $3 } function ltrim(s) { sub(/^[[:space:]]+/, "", s); return s }
解释:
- 自定义
ltrim函数去除字符串开头的空白 - 通过计算原行长度减去去空白后的长度,得到行首空白的长度,再用
substr提取原始空格 - 最后拼接空格、$1和$3输出
方法3:使用gensub直接替换不需要的字段
另一种思路是直接把第二个字段(包括其前后的空白)替换为空,只保留行首空格、第一个字段和第三个字段:
{ print gensub(/^([[:space:]]+\S+)\s+\S+\s+(.*)/, "\\1 \\2", 1) }
解释:
- 正则表达式
^([[:space:]]+\S+)\s+\S+\s+(.*)捕获三个部分:行首空格+第一个字段、第二个字段、第三个字段及后续内容 - 替换为
\\1 \\2,即保留第一部分和第三部分,中间用空格分隔,刚好符合需求
内容的提问来源于stack exchange,提问作者Philippe le peuch
相关产品推荐
相关产品推荐

