如何用sed匹配从指定字符串到固定位置的内容
用sed/awk实现固定位置内的匹配替换
问题描述
给定输入文本:
123456789 ABfooEFGH MNOPfooYZ
需要实现:匹配以指定字符串(示例中为foo)开头、到第N位(示例中为第8位,含)结束的子串,将其替换为bar。期望输出:
123456789 ABbarH MNOPbarZ
用户最初设想的sed伪命令为:
sed -E 's/foo.<8>/bar/' input.txt
其中. <8>为自定义语法,意为“匹配任意字符直到固定位置8(含)”。
实际场景补充
- 匹配字符串为bash变量(非硬编码的
foo) - 固定位置为bash变量
- 匹配字符串始终出现在固定位置之前
解决方案
方法1:结合bash循环处理
利用bash的字符串截取功能,拆分每行的前N位和剩余部分,在前置部分完成替换后拼接结果:
#!/bin/bash PATTERN="foo" POS=8 while IFS= read -r line; do # 截取前POS位内容 prefix="${line:0:$POS}" # 截取POS位之后的内容 suffix="${line:$POS}" # 替换prefix中PATTERN及其后续所有内容为bar new_prefix="${prefix//$PATTERN*/bar}" # 拼接输出 echo "$new_prefix$suffix" done < input.txt
方法2:用awk实现(更简洁高效)
awk支持直接处理字符串位置和变量,逻辑清晰:
#!/bin/bash PATTERN="foo" POS=8 awk -v pat="$PATTERN" -v pos="$POS" '{ pat_len = length(pat) # 查找匹配串的起始位置 start_idx = index($0, pat) if (start_idx > 0 && start_idx + pat_len - 1 <= pos) { # 截取匹配串之前的前缀 prefix = substr($0, 1, start_idx - 1) # 截取固定位置之后的后缀 suffix = substr($0, pos + 1) print prefix "bar" suffix } else { # 无匹配或匹配串超出固定位置,直接输出原行 print $0 } }' input.txt
方法3:纯sed实现(需构造动态正则)
如果必须用sed,可以通过bash计算匹配串长度,构造正则表达式:
#!/bin/bash PATTERN="foo" POS=8 pat_len=${#PATTERN} # 匹配行首到固定位置内的匹配串及其后续内容,替换为bar sed -E "s/^(.{0,$((POS - pat_len))})$PATTERN.*/\1bar/" input.txt
注:此方法默认匹配串在每行前POS位内唯一存在,若有多个匹配需额外调整正则。
内容的提问来源于stack exchange,提问作者benxyzzy
相关产品推荐
相关产品推荐

