Shell中如何将namelist.txt的姓名放在自增数字前并输出到新文件
可直接落地的实现方案
最简洁高效的方式是用awk完成全流程处理,全程不需要写多层shell循环,命令执行后直接生成符合要求的结果文件:
awk 'BEGIN{print "ID;name"} {split($0, parts, / \| /); split(parts[1], name_part, /:/); print NR+10000 ":" name_part[2]}' namelist.txt > output.txt
逻辑说明
- 开头的BEGIN块专门用来生成要求的表头
ID;name - awk内置的
NR变量会自动统计当前处理的行号(从1开始计数),直接加10000就满足ID的生成规则 - 第一次split按行中的
|分隔符拆分整行,拿到前半段Name:xxx的内容;第二次split按冒号拆分这段文本,直接提取冒号后的姓名内容 - 整个命令的输出直接通过
>重定向符写入output.txt,shell的重定向完全支持这类文件写入场景,不存在兼容问题。
原有代码的问题
- 语法错误:你写的
nut = $(awk '{print (NR)}' namelist.txt)在赋值时等号两侧留了空格,bash会将nut识别为待执行的命令,根本无法正常拿到行号值 - 逻辑缺失:原有循环只计算了ID数字,完全没有逐行读取源文件内容、提取对应姓名的步骤,自然拼不出完整的输出行
- 效率问题:单独提取所有行号再循环的写法,会额外启动多次子进程,处理大文件时性能远低于直接在awk中逐行处理的方式
偏好shell循环写法的修正版本
如果你希望沿着原来的循环思路写,可以参考下面的修正代码,一样能达到预期效果:
# 先写入表头 echo "ID;name" > output.txt current_line=0 # 逐行读取源文件 while read -r line; do current_line=$((current_line + 1)) id=$((current_line + 10000)) # 从当前行切割提取姓名,xargs用于去掉文本前后的多余空格 name=$(echo "$line" | cut -d: -f2 | cut -d'|' -f1 | xargs) # 拼接结果追加到文件 echo "${id}:${name}" >> output.txt done < namelist.txt
最终生成的output.txt内容完全和预期一致:
ID;name 10001:Mary Miller 10002:Harry Jonhson
内容的提问来源于stack exchange,提问作者improve
相关产品推荐
相关产品推荐

