Sed 就地更换

Sed 就地更换,sed,awk,Sed,Awk,我有一个CSV。我想编辑CSV的第35个字段,并将更改写回第35个字段。这就是我在bash上所做的: awk -F "," '{print $35}' test.csv | sed -i 's/^0/+91/g' 因此,我使用awk拉取第35个条目,然后将字符串起始位置的“0”替换为“+91”。这一个在perfet中工作,我在控制台上获得了所需的输出 现在我想把这个新条目写入文件。我正在考虑sed的“就地”替换功能,但是这个节日需要输入文件。在上面的命令中,我无法提供输入文件,因为我的主命令

我有一个CSV。我想编辑CSV的第35个字段,并将更改写回第35个字段。这就是我在bash上所做的:

awk -F "," '{print $35}' test.csv  | sed -i 's/^0/+91/g'
因此,我使用awk拉取第35个条目,然后将字符串起始位置的“0”替换为“+91”。这一个在perfet中工作,我在控制台上获得了所需的输出

现在我想把这个新条目写入文件。我正在考虑sed的“就地”替换功能,但是这个节日需要输入文件。在上面的命令中,我无法提供输入文件,因为我的主命令是awk,sed从awk获取输入


谢谢。

您应该从两种工具中选择一种。对于
sed
,可以按如下方式执行:

sed -ri 's/^(([^,]*,){34})0([^,]*)/\1+91\3/' test.csv 

关于
awk
,我不太清楚,但是@sheller的评论可能会有所帮助。

sed的
就地
功能命名错误,因为它没有就地编辑文件。相反,它会创建一个同名的新文件。例如:

$ echo foo > foo
$ ln -f foo bar
$ ls -i foo bar  # These are the same file
797325 bar  797325 foo
$ echo new-text > foo  # Changes bar
$ cat bar
new-text
$ printf '/new/s//newer\nw\nq\n' | ed foo  # Edit foo "in-place"; changes bar
9
newer-text
11
$ cat bar
newer-text
$ ls -i foo bar  # Still the same file
797325 bar  797325 foo
$ sed -i s/new/newer/ foo   # Does not edit in-place; creates a new file
$ ls -i foo bar
797325 bar  792722 foo    
由于sed实际上不是在原地编辑文件,而是编写一个新文件,然后将其重命名为旧文件,因此您也可以这样做

awk ... test.csv | sed ... > test.csv.1 && mv test.csv.1 test.csv

有一种误解,即使用
sed-i
某种程度上可以避免创建临时文件。事实并非如此。它只是对你隐瞒了事实。有时抽象是一件好事,但有时它是不必要的混淆。在sed-i的情况下,它是后者。shell非常擅长文件操作。按预期使用它。如果确实需要就地编辑文件,请不要使用流式版本的
ed
;只需使用
ed

这可能适合您:

sed -i 's/[^,]*/+91/35' test.csv
编辑:

要替换第35个字段中的前导零:

sed 'h;s/[^,]*/\n&/35;/\n0/!{x;b};s//+91/' test.csv
或者更简单地说:

|sed 's/^\(\([^,]*,\)\{34\}\)0/\1+91/' test.csv

所以,有很多方法可以做到这一点。我与sed的合作如下:

sed-i's/0\([0-9]\{10\}\)/\+91\1/g'test.csv

但这有点棘手,因为它将编辑任何符合条件的条目。然而,在我的情况下,它运行良好

上述逻辑在perl中的类似实现:

perl-p-i-e's/\b0(\d{10})\b/\+91$1/g;'test.csv

同样,上述警告也是一样的

更精确的方法如Lev Levitsky所示,因为它将专门在第35场上运行

sed-ri的/^([^,]*,){34})0([^,]*)/\1+91\3/g'test.csv

对于更复杂的情况,我将不得不考虑使用perl .< /p>中的任何CSV模块。 感谢大家的时间和投入。阅读您的回复后,我肯定对sed/awk有了更多了解。

如果您已经安装了,只需使用
海绵
工具即可:

awk -F "," '{print $35}' test.csv  | sed -i 's/^0/+91/g' | sponge test.csv
scape
吸收输入,关闭输入管道(stdin),然后打开并写入
test.csv
文件


截至2015年,moreutils已在几个主要Linux发行版的软件包存储库中提供,例如,和。

另一个用于在位编辑第35个字段的perl解决方案:

perl-i-F,-lane'$F[34]=~s/^0/+91/;打印join“,”,@F'test.csv

使用以下命令行选项:

  • -i
    就地编辑文件
  • -n
    循环输入文件的每一行
  • -l
    在处理之前删除换行符,然后将其添加回
  • -a
    自动拆分模式–将输入行拆分为
    @F
    数组。默认为按空格拆分
  • -e
    执行perl代码
  • -F
    自动拆分修改器,在本例中,在
    上拆分,
@F
是每行中的单词数组,索引从0开始
$F[34]
是数组的35个元素

s/^0/+91/
替换是否

您知道您可以在awk中使用
sub(/^0/,“+91”,$35)
?祝你好运。我运行了
awk-F“,”{'sub(/^0/,“+91”,$35);print$35'}test.csv
,它在控制台上进行替换,但不将更改写入文件。顺便说一句,谢谢你的信息,这对我来说是新的:)谢谢。将输出重定向到新文件只会复制第35列,即已编辑的列。不管怎么说,我正在研究它,一旦我有了答案,我会发布我的答案。谢谢您的时间。使用perl比使用sed/awk容易得多。这里是我如何让它工作的
perl-p-I-e's/\b0(\d{10})\b/\+91$1/g;test.csv
。这个答案是由帕尔蒙克的一位僧侣提供的。但我仍在努力使它与sed/awk一起工作:)这一个不起作用。但我想我可以对你的命令做一些调整。谢谢。@Dheeraj如果您至少提供一行示例输入,我很乐意为您提供帮助。@Dheeraj事实上我想我已经找到了问题所在,编辑过的命令应该可以更好地工作。无论如何,当提出此类问题时,请提供一些示例输入供我们使用。很抱歉没有获得示例输入。我会确保在我未来的问题中添加广告。您编辑的命令无效,但感谢您的指导。我会调整它,并希望它能起作用。谢谢您的时间Lev.BTW,以下是示例:
foo,foo,foo,,,,,,,,,,,,,,,,,*我的联系人:::仅限手机,,,,,,,,,,,,,手机,01234567899,,,,,,,,,,,,,,,,,
。因此,在这一行中,我想将
01234567899
更改为
+911234567899
,部分更改为,但它将第35个字段替换为“+91”,并省略剩余的数字。哇。我可以在
s
中将出现次数指定为标志?还能有什么?我只知道
g
p
。。。