我需要找到一个 sed/awk 命令,它将在长度为 10 的匹配字符串的第 n 个位置插入一个字符。例如,我需要搜索以 pattern 开头541
且长度为 10 的字符串,然后9
在第 5 个位置插入该字符串不进行替换,从而得到 11 个字符的字符串。
字符串是由空格分隔的单词。此外,模式始终位于单词的开头,但每行可能有多个匹配项。
输入文件:
5414444444 87654873234 88888888888
6646666666 54122222222
54155555558888 54176543235 5416666666
输出文件:
54149444444 87654873234 88888888888
6646666666 54122222222
54155555558888 54176543235 54169666666
答案1
从示例中可以看出 OP 的意思是 aword
不是string
so
sed 's/\b541./&9/g' file
如果541
可以从word中的其他地方开始(不是从头开始)
sed 's/\b\S*541/\n&/g #mark a beginning of word(s) with pattern
s/\n\(....\)/\19/g #remove mark and do adding
' file
您可以限制单词的符号数量,如下所示
sed 's/\b\(541.\)\(\S\{6\}\)\b/\19\2/g' file
或更一般的
sed 's/\b541./&\n/g;s/\n\S\{6\}\b/9&/g;s/\n//g' file
答案2
你可以使用perl
perl -lane 'map{length==10&&/^541/&&s/.{4}/$&9/}@F;print join(" ",@F)' file
使用映射对每个字段执行检查和子操作。然后打印由单个空格连接的字段数组(如果字段之间的单个空格不一致,则会弄乱格式)
或者只是使用正则表达式
perl -lane 'map{s/^541.\K.{6}$/9$&/}@F;print join(" ",@F)' file
输出:
54149444444 87654873234 88888888888
6646666666 54122222222
54155555558888 54176543235 54169666666
答案3
便携:
sed '
s/.*/ & /; # add a leading and trailing space
:1
s/\([[:blank:]]541[^[:blank:]]\{2\}\)\([^[:blank:]]\{5\}[[:blank:]]\)/\19\2/g
# replace in a loop until there is no more match
t1
# remove the blanks we added earlier:
s/^ //;s/ $//'
除了后面/前面的空白之外,您还可以通过在列表的开头或结尾查找该 10 个非空白字符串的出现来避免临时添加前导空格和尾随空格。这可以通过一个正则表达式以 POSIX 方式完成,但这有点笨拙:
sed '
:1
s/^\(\(.*[[:blank:]]\)\{0,1\}541[^[:blank:]]\{2\}\)\([^[:blank:]]\{5\}\([[:blank:]].*\)\{0,1\}\)$/\19\3/
t1'
与perl
, 使用环视运算符:
perl -lpe 's/((?<!\H)541\H\H)(\H{5})(?!\H)/${1}9$2/g'
或者一一处理单词:
perl -lpe 's{\H+}{$&=~s/^541..\K.{5}$/9$&/r}ge'
(\K
并且r
替换标志需要相对较新的版本perl
)。