Shell脚本用sed

时间:2017-02-02 14:15:38

标签: shell sed

我有一个以分号分隔的示例数据集,如下所示;

123;IZMIR;ZMIR;123
abc;ANKAR;aaa;999
AAA;ZMIR;ZMIR;bob
BBB;ANKR;RRRR;ABC

我想替换指定列中的值。让我们说我想改变" ZMIR" AS" IZMIR"但只有第三列,第二列的那些必须保持不变。

所需的输出是;

123;IZMIR;IZMIR;123
abc;ANKAR;aaa;999
AAA;ZMIR;IZMIR;bob
BBB;ANKR;RRRR;ABC

我试过了;

sed 's/;ZMIR;/;IZMIR;/' file.txt
问题是它改变了文件上的所有值而不仅仅是第三个值。

我也试过了;

awk -F";" '{gsub("ZMIR",";IZMIR;",$2)}1'

并且在这里它指定了列,但它以某种方式添加了空格;

123 I;IZMIR; ZMIR 123
abc;ANKAR;aaa;999
AAA ;IZMIR; ZMIR bob
BBB;ANKR;RRRR;ABC

5 个答案:

答案 0 :(得分:0)

sed不知道列,awk不知道(但是在awk中他们被称为"字段"):

awk 'BEGIN{FS=OFS=";"} $3=="ZMIR"{$3="IZMIR"} 1' file

请注意,由于上面的文字字符串搜索和替换,您不必担心搜索或替换字符串中的regexp或反向引用元字符,这与sed解决方案不同(请参阅https://stackoverflow.com/a/29626460/1745001 )。

你之前用awk尝试了什么:

awk -F";" '{gsub("ZMIR",";IZMIR;",$2)}1'

那说:find "ZMIR" in the 2nd semi-colon-separated field and replace it with ";IZMIR;" and also change every existing ";" on the line to a blank character

要学习awk,请阅读Arnold Robbins撰写的Effective Awk Programming,4th Edition。

答案 1 :(得分:0)

如果您确切知道要替换的单词所在的位置以及它们中有多少位于该行中,您可以将sed用于以下内容:

sed '3 s/ZMIR/IZMIR/2'

在开头使用3时,您选择第三行,最后使用2,第二次出现。然而,awk解决方案更好。但只是你知道它在sed中是如何工作的;)

答案 2 :(得分:0)

这可能适合你(GNU sed):

sed -r 's/[^;]+/\n&\n/3;s/\nZMIR\n/IZMIR/;s/\n//g' file

通过唯一标记环绕所需字段,然后用替换字符串替换所需字符串(加上标记)。最后删除独特的标记。

答案 3 :(得分:0)

命令行上的Perl

输入

123;IZMIR;ZMIR;123  
000;ANKAR;aaa;999  
AAA;ZMIR;ZMIR;bob  
BBB;ANKR;RRRR;ABC    

$. == 1表示第一个仅对此起作用所以第二个 $. == 2
$F[0]表示第一个,它仅适用于此所以第四个 $F[3]
-a -F\;表示分隔符为;

你想要什么
perl -a -F\; -pe 's/$F[0]/***/ if $. == 1' your-file

输出

***;IZMIR;ZMIR;123  
abc;ANKAR;aaa;999  
AAA;ZMIR;ZMIR;bob  
BBB;ANKR;RRRR;ABC   

行== 2 列== 2
perl -a -F\; -pe 's/$F[1]/***/ if $. == 2' your-file

123;IZMIR;ZMIR;123  
abc;***;aaa;999  
AAA;ZMIR;ZMIR;bob  
BBB;ANKR;RRRR;ABC    

也没有-a -F
perl -pe 's/123/***/ if $. == 1' your-file

输出

***;IZMIR;ZMIR;123  
abc;ANKAR;aaa;999  
AAA;ZMIR;ZMIR;bob  
BBB;ANKR;RRRR;ABC   

如果您想要修改,可以添加-i选项,意味着就地编辑这就是它,它只是查找,替换并保存在同一个文件中<登记/> perl -i -a -F\;等等

答案 4 :(得分:-1)

您需要在行中包含一些绝对引用:

  • ^开头行
  • 明确的分离模式
  • ^.*ZMIR[^;]*;ZMIR给出了不同的值,首先在ZMIR之前采取一切,sed采取尽可能长的

具体

sed 's/^\([^;]*;[^;]*;\)ZMIR;/\1IZMIR;/' YourFile

通用,其中是批量变量(请记住,这是正则表达式值,因此正则表达式适用于转义,例如转义某些字符)

#Old='ZMIR'
#New='IZMIR'

sed 's/^\(\([^;]*;\)\{2\}\)'${Old}';/\1'${New}';/' YourFile

在这种简单的情况下,sed是另一种选择,但awk对于复杂或长线更好。