AIX下用AWK实现cut --complement功能的技术咨询
嘿,刚好在AIX上碰到过类似的问题,cut没有--complement参数确实挺头疼的,不过用AWK可以完美替代你需要的这两种场景需求,我把两种情况的实现方案都整理好了:
1. 替代
cut --complement -c $IGNORE_RANGE(按字符位置排除) 核心思路是先把$IGNORE_RANGE里的字符范围解析成一个要排除的位置集合,然后遍历每行的每个字符,只保留不在这个集合里的字符。
完整的AWK命令如下:
awk -v ignore="$IGNORE_RANGE" ' BEGIN { # 解析忽略范围字符串,生成排除位置的标记数组 split(ignore, parts, ",") for (i in parts) { # 处理连续范围(如1-5) if (parts[i] ~ /-/) { split(parts[i], range, "-") start = range[1] end = range[2] for (j=start; j<=end; j++) { exclude[j] = 1 } } # 处理单个位置(如6) else { exclude[parts[i]] = 1 } } } { result = "" # 遍历每行的每个字符,筛选保留未被排除的 for (k=1; k<=length($0); k++) { if (!exclude[k]) { result = result substr($0, k, 1) } } print result }' file.txt > tmp
示例验证
- 当
$IGNORE_RANGE=1-5,6,输入行是abcdefg时,输出g;输入行是1234567时,输出7,和原cut命令结果一致。 - 当
$IGNORE_RANGE=1,3,5,输入行是abcdefg时,输出bdfg;输入行是1234567时,输出2467,符合预期。
2. 替代
cut --complement -d, -f$IGNORE_RANGE(按字段排除,逗号分隔) 思路和字符场景类似,先解析要排除的字段范围,然后遍历每行的字段,保留未被排除的字段,最后用指定分隔符拼接输出。
完整的AWK命令如下:
awk -v delimiter="," -v ignore="$IGNORE_RANGE" ' BEGIN { FS = delimiter # 设置输入分隔符 OFS = delimiter # 设置输出分隔符 # 解析忽略范围,生成排除字段的标记数组 split(ignore, parts, ",") for (i in parts) { if (parts[i] ~ /-/) { split(parts[i], range, "-") start = range[1] end = range[2] for (j=start; j<=end; j++) { exclude[j] = 1 } } else { exclude[parts[i]] = 1 } } } { result = "" first_field = 1 # 遍历每行的所有字段,筛选保留未被排除的 for (k=1; k<=NF; k++) { if (!exclude[k]) { if (first_field) { result = $k first_field = 0 } else { result = result OFS $k } } } print result }' "$report" > tmp
示例验证
- 当
$IGNORE_RANGE=1-5,6,输入行是data1,data2,data3,data4,data5,data6,data7时,输出data7。 - 当
$IGNORE_RANGE=1,3,5,输入行同上时,输出data2,data4,data6,data7,和原cut命令结果完全一致。
额外说明
如果你的分隔符不是逗号,只需要修改-v delimiter="你的分隔符"即可,比如要用制表符分隔的话,改成-v delimiter="\t"就行。
内容的提问来源于stack exchange,提问作者Rasmi
相关产品推荐
相关产品推荐

