使用awk与printf提取文本列时出现额外换行问题求助
问题根因
- shell的
for循环默认分隔符逻辑问题:未自定义IFS(内部字段分隔符)的情况下,for line in $(awk ...)会把输出内容中的空格、制表符、换行符都识别为字段分隔符,原本awk输出的「字段1 字段2 字段3」整行结构会被拆成3个独立的循环元素,每次循环的line变量仅拿到单个字段,打印时自然每个字段单独占一行。 - awk格式化参数错误:你使用
%i(整数格式符)处理第二列内容,而第二列末尾带字母Z(如220504203222Z),会导致Z被截断,不符合保留原始内容的需求。 - 字段匹配偏差:R状态的行比V状态的行多了一个「撤销时间」字段,R行的第5列是
unknown,并非你要的证书主题,如果需要统一匹配证书主题字段,应该取每行最后一列而非固定第5列。 - 逻辑冗余:过滤R开头的行完全可以在awk阶段完成,不需要输出到shell再做判断,既降低效率还容易引入shell解析问题。
正确实现方案
推荐只用awk一条命令完成所有需求,完全规避分隔符类问题:
#!/bin/bash index="/opt/easy-rsa/easyrsa3/pki/index.txt" # 如果你确认要取固定第5列用这个写法 awk '$1 != "R" {print $1, $2, $5}' "$index" # 如果你要统一取每行最后的证书主题,用$NF替代$5即可 # awk '$1 != "R" {print $1, $2, $NF}' "$index"
如果一定要保留shell循环的写法(不推荐),需要临时修改IFS规则:
#!/bin/bash index="/opt/easy-rsa/easyrsa3/pki/index.txt" # 备份原有IFS配置,临时设置仅换行作为分隔符 OLD_IFS="$IFS" IFS=$'\n' # 关闭通配符展开,避免文件名特殊字符导致异常 set -f for line in $(awk '{print $1, $2, $5}' "$index"); do if ! [[ ${line} =~ ^R.* ]]; then printf "%s\n" "$line" fi done # 恢复原有shell配置 IFS="$OLD_IFS" set +f
内容的提问来源于stack exchange,提问作者Fang
相关产品推荐
相关产品推荐

