2016-01-23 77 views
1

比方说我的数据看起来像这样替换字符

iqwertyuiop 

,我想替换所有字母我一个Z列后3 ..所以我的输出看起来像这样

iqwertyuZop 

我该怎么用sed或awk做到这一点?

回答

3

目前尚不清楚你的意思是“列”,但也许这是你想要使用GNU AWK的gensub()什么:

$ echo iqwertyuiop | awk '{print substr($0,1,3) gensub(/i/,"Z","g",substr($0,4))}' 
iqwertyuZop 
1

最直观的方法是使用awk

awk 'BEGIN{FS="";OFS=FS}{for(i=4;i<=NF;i++){if($i=="i"){$i="Z"}}}1' file 

FS=""由字符将输入字符串转换成田。我们迭代低谷字符/字段4结束并用Z替换i

最后的1评估为true并且使awk打印修改的输入行。


随着sed它看起来不是很intutive但它仍然是可能的:

sed -r ' 
    h      # Backup the current line in hold buffer 
    s/.{3}//    # Remove the first three characters 
    s/i/Z/g    # Replace all i by Z 
    G      # Append the contents of the hold buffer to the pattern buffer (this adds a newline between them) 
    s/(.*)\n(.{3}).*/\2\1/ # Remove that newline ^^^ and assemble the result 
' file   
+0

你能不能1)使用'y/i/Z /'(保存一个完整的字符!)2)而不是'x; s; G; s' do'G; s /(。*)\ n(...)。*/\ 2 \ 1 /'? –

+0

@BenjaminW。1)'y'命令在多行版本后需要一个';',如果它后面有注释。不要问我为什么。 2)好点!补充说 – hek2mgl

1

这完全是理想的tr命令,只要你没有要求前3字符保持不变。

但是,如果你是没事使用一些bash的技巧加上cutpaste,你可以将文件分割成两个部分,并将其粘贴到一起后记:

paste -d'\0' <(cut -c-3 foo) <(cut -c4- foo | tr i Z) 

上述用途paste两个归队一起与cut分开的文件部分。第二部分通过tr通过管道将i转换为Z's。

1

(1)下面是完成一个短期和简单的方法任务使用GNU sed的:

sed -r -e ':a;s/^(...)([^i]*)i/\1\2Z/g;ta' 

这需要循环(t),所以不会像非循环的方法一样有效。上面也可以使用转义括号而不是非转义字符来编写,因此不需要-r选项。 sed的其他实现应该(原则上)完成任务,但是您的MMV。

(2)这是很容易使用, “旧的AWK” 以及:

awk '{s=substr($0,4);gsub(/i/,"Z",s); print substr($0,1,3) s}' 
3

Perl是得心应手这样的:你可以分配到子

$ echo "iiiiii" | perl -pe 'substr($_,3) =~ s/i/Z/g' 
iiiZZZ