我是sed
的新手,我想弄清楚是否可以为行中字符串匹配后遇到的两个标记之间的所有单词添加前缀
假设我有一行
abc xyz PAT1 { PAT2 PAT3 PAT4 } cdf fgd
PAT1
是字符串匹配,在这种情况下标记为{ and }
我希望结果是
abc xyz PAT1 { prefix_PAT2 _prefix_PAT3 prefix_PAT4 } cdf fgd
我可以编写一个C代码来执行此操作,但我不熟悉脚本,所以我想知道sed
是否可以使用它?
我知道如果遇到字符串,如何为行的某些列添加前缀
但PAT2 PAT3 PAT4
可以是任何列,可能有超过3列
答案 0 :(得分:1)
考虑这个输入文件:
$ cat file
abc xyz { PAT2 PAT3 PAT4 } cdf fgd
abc xyz PAT1 { PAT2 PAT3 PAT4 } cdf fgd
使用GNU sed:
$ sed ':a; s/\(PAT1.*{[^}\n]*\)\b\([[:alnum:]]\)/\1\n\2/; t a; s/\n/prefix_/g' file
abc xyz { PAT2 PAT3 PAT4 } cdf fgd
abc xyz PAT1 { prefix_PAT2 prefix_PAT3 prefix_PAT4 } cdf fgd
:a
这定义了标签a
。
s/\(PAT1.*{[^}\n]*\)\b\([[:alnum:]]\)/\1\n\2/
如果PAT1
位于大括号之前,则会在大括号内的单词前面添加换行符。
更详细:
\(PAT1.*{[^}\n]*\)
PAT1.*{[^}\n]*
查找PAT1
,后跟任何内容,然后是{
,后跟}
或换行符以外的任何字符。围绕此表达式\(PAT1.*{[^}\n]*\)
的转义的parens会导致其匹配的任何内容保存为组1,表示为\1
。
\b
这与单词之间的中断相匹配。
\([[:alnum:]]\)
这匹配任何字母数字字符。因为它在单词之间断开,所以这个字符是新单词的开头。 (我允许数字开头。如果不希望这样做,请将alnum
更改为alpha
。因为它被转义的parens所包围,所以这些匹配的内容都保存为第2组,\2
如上所述匹配的内容将替换为\1\n\2
,即第一组,换行符和第二组。总而言之,这会在PAT1
之后的大括号中出现换行符。
t a
如果上述命令确实导致替换,则跳回标签a
。换句话说,重复替换,直到所有单词前面都有换行符。
s/\n/prefix_/g
最后一步,用prefix_
替换换行符。
这里使用换行符作为占位符,因为我们可以确定它永远不会出现在sed读取的行中。 (否则它不会是一条线。)
以上使用\b
来匹配单词边界。它还在替换中使用\n
。 GNU sed可以很好地处理这两个问题。其他seds可能需要也可能不需要对代码进行一些调整。
答案 1 :(得分:1)
输入文件包含:
abc xyz PAT1 { PAT2 PAT3 PAT4 } cdf fg
尝试以下代码:
sed -i -e 's/PAT*/prefix_PAT/2g' filename
它会更新你的输入文件(文件名) 输出:
abc xyz PAT1 { prefix_PAT2 prefix_PAT3 prefix_PAT4 } cdf fgd