用在行首处找到的模式替换字符串

时间:2016-04-29 21:34:11

标签: string sed pattern-matching

我正在尝试使用sed来执行此操作:

我有一个空格分隔的文件,有5列,如下所示:

45_342 2 SEQUENCE_2 A G
234_43 45 SEQUENCE_45 T G
12_45 9 SEQUENCE_9 C C
1233_456 134 SEQUENCE_134 T A

我正在尝试将每行中的字符串“SEQUENCE”替换为在同一行开头找到的模式。我应该获得:

45_342 2 45_342_2 A G
234_43 45 234_43_45 T G
12_45 9 12_45_9 C C
1233_456 134 1233_456_134 T A

我尝试将此逻辑与以下sed命令一起使用:

sed -i '/PatternAtBeginnigOfLine/s/SEQUENCE/PatternAtBeginnigOfLine/g' ./file 

我的sed代码如下:

sed -i '/^[0-9]\+_[0-9]\+\s/s/SEQUENCE/^[0-9]\+_[0-9]\+/g' ./file 

但是我最终得到了这个结果

45_342 2 ^[0-9]\+_[0-9]\+_2 A G
234_43 45 ^[0-9]\+_[0-9]\+_45 T G
12_45 9 ^[0-9]\+_[0-9]\+_9 C C
1233_456 134 ^[0-9]\+_[0-9]\+_134 T A

对于我所做错的任何建议都将不胜感激。

3 个答案:

答案 0 :(得分:1)

sed解决方案

$ sed -E 's/([^ ]+) ([^ ]+) SEQUENCE/\1 \2 \1/' ./file 
45_342 2 45_342_2 A G
234_43 45 234_43_45 T G
12_45 9 12_45_9 C C
1233_456 134 1233_456_134 T A

或者,要更改文件,请添加-i选项:

sed -i -E 's/([^ ]+) ([^ ]+) SEQUENCE/\1 \2 \1/' ./file 

如何运作

s(替换)命令的格式为s/old/new/。在我们的例子中,old模式包括:

([^ ]+) ([^ ]+) SEQUENCE

由于括号,它会捕获第1组中的第一列和第2组中的第二列。

new文字如下:

\1 \2 \1

这意味着匹配的文本将替换为第一个组,表示为\1,一个空格,第二个组,表示为\2,一个空格,以及第一个组。

注意:

  • 我添加了-E标志,告诉sed使用扩展正则表达式。这避免了需要大量的反斜杠转义。

  • 由于我们希望每行只执行一次此替换,因此替换命令不需要g修饰符

awk解决方案

为了完整起见,这是一个使用awk的解决方案:

$ awk '{sub("SEQUENCE", $1, $3)} 1' file
45_342 2 45_342_2 A G
234_43 45 234_43_45 T G
12_45 9 12_45_9 C C
1233_456 134 1233_456_134 T A

要就地更改文件(假设你有一个现代的GNU awk):

awk -i inplace '{sub("SEQUENCE", $1, $3)} 1' file

如何运作

  • sub("SEQUENCE", $1, $3)

    这会在第三个字段中查找SEQUENCE(表示为$3)。如果找到,则将其替换为第一个字段(表示为$1)。

  • 1

    这是用于打印线的awk简洁速记。

答案 1 :(得分:0)

这是一个小的Bash脚本:

while read -r col0 col1 col2 rest; do
    printf "%s %s %s %s\n" "$col0" "$col1" "${col2/SEQUENCE/$col0}" "$rest"
done < infile

while read -r ...; do ... done < infile循环逐行读取输入文件,并不解释反斜杠序列(-r标志)。

使用shell word splitting拆分该行,在本例中为空格。前三个字段分配给col个参数,其余部分分配到rest

printf行基本上打印相同的行,但使用parameter expansion将第一个字段的值替换为第三个字段中的SEQUENCE

结果如下:

45_342 2 45_342_2 A G
234_43 45 234_43_45 T G
12_45 9 12_45_9 C C
1233_456 134 1233_456_134 T A

如果你要计时,sed和awk解决方案,你很可能会发现sed比这更快,并且比sed更快。

答案 2 :(得分:0)

NodeList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];