我有一个带有嵌入换行符的csv文件。
我想做的是用不同的EOL字符重写每一行,以便其他CSV阅读器解析更简单。
为此,我知道每个新行都以正则表达式开头/ \ n" \ d +"," / - 这是换行符,引号,一些数字,另一个引号,逗号,然后另一个引用。
我可能错了,但是sed,awk和其他大多数工具都期望最后换行。是否有一个没有的Linux工具?
我的下一个想法是使用awk继续读取行并将它们推送到缓冲区,直到它找到一个以上面的表达式开头 - 然后它会写出来。
答案 0 :(得分:1)
好的,让我们看看我是否理解你想要的东西。给出像
这样的csv文件"123","foo
bar","baz"
"234","quxqux"
"345","xy
zz
y","asd"
你希望它变成像
这样的东西"123","fooNEWLINEbar","baz"
"234","quxqux"
"345","xyNEWLINEzzNEWLINEy","asd"
然后,我可以在短时间内发出最好的声音(没有回到准备保持理智的sed文档)是这个sed脚本:
/^"[0-9]\+","/ !H
/^"[0-9]\+","/ {
x
s/\n/NEWLINE/g
p
x
h
}
$ {
x
s/\n/NEWLINE/g
p
x
h
}
如果代码在文件foo.sed
中,则使用,如下所示:
sed -n -f foo.sed foo.csv
<强>解释强>
这涉及到sed的一些较少使用的功能,因此我将简要解释两个基本机制:
表单
的sed命令/regex1/ command
将命令应用于regex1
可以匹配的所有行。例如,
/^1/ s/2/3/g
在以2
开头的所有行中,将3
替换为1
s。 !
反转匹配,所以
/^1/ !s/2/3/g
在不以1开头的所有行中用2
替换3
s。命令可以与{}
这是sed鲜为人知但非常强大的功能之一。大多数sed命令都适用于模式空间。模式空间是写入新输入行的位置,因此命令可以对它们起作用,因此如果您单独处理行,则此机制对您来说是透明的。此外,sed有一个保持缓冲区,您可以保留以前的输入,因为您以后需要它。只有少数命令可用于保持缓冲区;其中三个是我们感兴趣的:h
,H
和x
。 h
将模式空间的当前内容(通常是刚刚写入的输入行)复制到保持缓冲区。 H
将模式空间附加到保持缓冲区。 x
交换模式空间的内容并保留缓冲区。
逐块获取脚本:
/^"[0-9]\+","/ !H
这适用于不以"number","
H命令开头的所有行。这意味着这些行被附加到保持缓冲区。
/^"[0-9]\+","/ {
x
s/\n/NEWLINE/g
p
x
h
}
这适用于做以"number","
命令块开头的所有行。那就是:
最后,
$ {
x
s/\n/NEWLINE/g
p
x
h
}
对最后一行输入做同样的事情,因此CSV的最后一条逻辑行不会丢失。
这意味着&#34;逻辑行的所有部分&#34; CSV的组合在保持缓冲区中,当检测到下一个的开始时,组装的线被适当地修剪并打印。