就地更换

时间:2012-06-21 12:43:27

标签: sed awk

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

awk -F "," '{print $35}' test.csv  | sed -i 's/^0/+91/g'

所以,我使用awk拉出第35个条目,然后用“+91”替换字符串中起始位置的“0”。这个工作perfet我在控制台上获得所需的输出。

现在我想要将这个新条目写入文件中。我正在考虑sed的“in -place”替换功能,但这个胎儿需要和输入文件。在上面的命令中,我无法提供输入文件,因为我的主命令是awk而sed正在从awk获取输入。

感谢。

6 个答案:

答案 0 :(得分:47)

您应该选择这两种工具中的一种。至于sed,可以按如下方式完成:

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

不确定awk,但@ shellter的评论可能对此有所帮助。

答案 1 :(得分:16)

sed的in-place功能名称错误,因为它不会编辑文件。相反,它会创建一个具有相同名称的新文件。例如:

$ 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

答案 2 :(得分:2)

这可能对您有用:

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

答案 3 :(得分:2)

因此,事实证明有很多方法可以做到这一点。我使用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 's/^(([^,]*,){34})0([^,]*)/\1+91\3/g' test.csv

对于更复杂的情况,我将不得不考虑使用perl的任何csv模块。

感谢大家的时间和投入。在阅读你的回复后,我肯定对sed / awk了解得更多。

答案 4 :(得分:0)

如果您安装了moreutils,则可以使用sponge工具:

awk -F "," '{print $35}' test.csv  | sed -i 's/^0/+91/g' | sponge test.csv

sponge吸收输入,关闭输入管道(stdin),然后打开并写入test.csv文件。

截至2015年,moreutils可用于几个主要Linux发行版的软件包存储库,例如Arch LinuxDebianUbuntu

答案 5 :(得分:0)

另一个就地编辑第35个字段的perl解决方案:

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

使用以下命令行选项:

  • -i就地编辑文件
  • -n循环输入文件的每一行
  • -l在处理之前删除换行符,然后将其添加回来
  • -a autosplit模式 - 将输入行拆分为@F数组。默认为在空格上拆分。
  • -e执行perl代码
  • -F autosplit修饰符,在这种情况下会在,
  • 上拆分

@F是每行中的单词数组,从0开始索引 $F[34]是数组的35个元素 s/^0/+91/执行替换