如何用AWK实现仅拆分前N列,保留后续含空格内容?
AWK如何仅拆分前N列并保留后续内容的空格?
假设有一个文件,包含N个以空白字符分隔的列,以及一段需要保留空格的内容。以N=2为例,输入内容如下:
1.1 1.2 data for row1 2.1 2.2 data for row2 ? ? data for row3 \ * data for row4
期望输出为:
data for row1 data for row2 data for row3 data for row4
在Shell中可以通过以下代码轻松实现:
while read -r _ _ data do printf "%s\n" "$data" done < data.txt
但用awk实现似乎有难度,请问AWK中是否有仅拆分前N列的方法?
当然有,以下是几种实用的AWK实现方式:
方法1:正则替换移除前N列(通用简洁)
核心是用sub函数匹配开头的N列(含列间任意空白),替换为空后输出剩余内容。以N=2为例:
awk '{sub(/^[[:space:]]*[^[:space:]]+[[:space:]]+[^[:space:]]+[[:space:]]+/, ""); print}' data.txt
如果要适配任意N,可将N作为变量传入,动态生成正则:
awk -v N=2 '{ regex = "^[[:space:]]*" for (i=1; i<=N; i++) { regex = regex "[^[:space:]]+[[:space:]]+" } sub(regex, "") print }' data.txt
方法2:定位字段起始位置(精确保留原始空格)
通过遍历行内字符,找到第N+1个非空白字段的起始位置,截取从该位置到行尾的内容,完美保留原始空格格式:
awk -v N=2 '{ pos = 0 cnt = 0 for (i=1; i<=length($0); i++) { # 识别字段起始:当前是非空白,且前一个是空白或在行首 if (substr($0,i,1) ~ /[^[:space:]]/ && (i==1 || substr($0,i-1,1) ~ /[[:space:]]/)) { cnt++ if (cnt == N+1) { pos = i break } } } print pos > 0 ? substr($0, pos) : "" }' data.txt
方法3:GNU awk专属的gensub简化写法
GNU awk的gensub支持捕获组,可更简洁地完成替换:
awk -v N=2 '{print gensub("^[[:space:]]*(([^[:space:]]+[[:space:]]+){"N"})", "", 1)}' data.txt
内容的提问来源于stack exchange,提问作者Fravadona
相关产品推荐
相关产品推荐

