You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Vim中的sed命令转换为可在Bash脚本中运行的命令?

问题:将Vim中的行号替换命令迁移到Bash脚本

我在Vim里有两个实用的替换命令,想放到Bash脚本中批量处理文件,但试了各种sed的写法都无法正常工作。


需求1:更新行尾的8位序号

行内容长度不一,但都以空格+8位数字结尾,删除部分行后需要把这些序号更新为当前实际行号(8位格式)。

  • Vim中可用的命令:
    %s/\( \)[0-9]\{8\}$/\=printf(' %08d', line('.'))/g
    
  • 我尝试过的sed命令(无效):
    sed -i "s/\( \)[0-9]\{8\}$/\=printf(' %08d', line('.'))/g" input.txt
    

示例

输入:

321321321321321321321321321321321321321321321321321321 00000001
6546546546546546546546546546546546546546546546546546546546546546 00000003
987987987987987987987987987987987987987987987987987987987 00000004

预期输出:

321321321321321321321321321321321321321321321321321321 00000001
6546546546546546546546546546546546546546546546546546546546546546 00000002
987987987987987987987987987987987987987987987987987987987 00000003

需求2:替换文本中的LINENUMB为当前8位行号

把文件中所有的LINENUMB字符串替换为它所在行的行号(8位格式)。

  • Vim中可用的命令:
    %s/LINENUMB/\=printf('%08d', line('.'))/g
    

示例

输入(第206206行):

987654321LINENUMB123456789

预期输出:

98765432100206206123456789

解决方案:用Awk实现

sed不支持像Vim那样在替换中动态调用函数获取当前行号,而Awk可以轻松跟踪行号(NR变量表示当前行号),适合处理这类需求。

1. 更新行尾序号的命令

awk '{sub(/ [0-9]{8}$/, sprintf(" %08d", NR)); print}' input.txt > temp.tmp && mv temp.tmp input.txt

如果使用GNU Awk(大部分Linux系统默认是),可以直接用-i inplace参数修改原文件,省去临时文件:

awk -i inplace '{sub(/ [0-9]{8}$/, sprintf(" %08d", NR)); print}' input.txt

2. 替换LINENUMB的命令

awk '{gsub(/LINENUMB/, sprintf("%08d", NR)); print}' input.txt > temp.tmp && mv temp.tmp input.txt

同样,GNU Awk可以用-i inplace:

awk -i inplace '{gsub(/LINENUMB/, sprintf("%08d", NR)); print}' input.txt

封装成Bash脚本

可以把这两个功能写成脚本方便复用:

#!/bin/bash

# 更新文件行尾的8位序号为当前行号
update_line_suffix() {
    if [ $# -ne 1 ]; then
        echo "错误:请指定要处理的文件名"
        echo "用法:update_line_suffix <文件名>"
        return 1
    fi
    awk -i inplace '{sub(/ [0-9]{8}$/, sprintf(" %08d", NR)); print}' "$1"
}

# 将文件中所有LINENUMB替换为当前行号(8位格式)
replace_linenumb_tag() {
    if [ $# -ne 1 ]; then
        echo "错误:请指定要处理的文件名"
        echo "用法:replace_linenumb_tag <文件名>"
        return 1
    fi
    awk -i inplace '{gsub(/LINENUMB/, sprintf("%08d", NR)); print}' "$1"
}

# 调用示例(取消注释即可使用)
# update_line_suffix your_file.txt
# replace_linenumb_tag your_file.txt

内容的提问来源于stack exchange,提问作者Ron

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 16:07:00