在匹配字符串的第 n 个位置追加一个字符

在匹配字符串的第 n 个位置追加一个字符

我需要找到一个 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不是stringso

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)。

相关内容