我有一张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获取输入。
感谢。
答案 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 Linux,Debian和Ubuntu。
答案 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/
执行替换