25

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

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

因此,我使用 awk 拉出第 35 个条目,然后将字符串中起始位置的“0”替换为“+91”。这个效果很好,我在控制台上得到了想要的输出。

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

谢谢。

4

6 回答 6

47

您应该选择两种工具之一。至于sed,可以如下进行:

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

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

于 2012-06-21T12:48:27.110 回答
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

于 2012-06-21T15:14:35.767 回答
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
于 2012-06-21T16:39:31.803 回答
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 有更多了解。

于 2012-06-22T08:46:08.967 回答
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

于 2015-05-21T13:21:26.023 回答
0

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

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

使用这些命令行选项:

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

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

于 2015-11-13T00:24:07.720 回答