在一个脚本中加入多个sed命令以处理CSV文件


34

具有这样的CSV文件:

HEADER
"first, column"|"second "some random quotes" column"|"third ol' column"
FOOTER

并寻找类似的结果:

HEADER
first, column|second "some random quotes" column|third ol' column

换句话说,删除“ FOOTER”,在引号的开头,结尾和周围加引号。

到目前为止,此代码有效:

sed '/FOOTER/d' csv > csv1 | #remove FOOTER
sed 's/^\"//' csv1 > csv2 | #remove quote at the beginning
sed 's/\"$//' csv2 > csv3 | #remove quote at the end
sed 's/\"|\"/|/g' csv3 > csv4 #remove quotes around pipe

如您所见,问题在于它会创建4个额外的文件。

这是另一种解决方案,其目标是不创建额外的文件并在单个脚本中执行相同的操作。效果不是很好。

#!/bin/ksh

sed '/begin/, /end/ { 
        /FOOTER/d
        s/^\"//
        s/\"$//
        s/\"|\"/|/g 
}' csv > csv4

1
由于您使用引号,因此可以在字段中使用换行符。您sed将无法使用它,而只能使用简化的csv。将编程语言与可以处理实际CSV文件的库一起使用(Python / Perl / Ruby)。
Anthon

Answers:


44

首先,如Michael所示,您可以将所有这些合并为一个命令:

sed '/^FOOTER/d; s/^\"//; s/\"$//; s/\"|\"/|/g' csv > csv1

我认为某些sed实现无法解决这一问题,可能需要:

  sed -e '/^FOOTER/d' -e 's/^\"//' -e 's/\"$//' -e 's/\"|\"/|/g' csv > csv1

就是说,您的字段似乎是由定义的|,您只想删除"整个字段,而保留字段中的内容。在这种情况下,您可以执行以下操作:

$ sed '/FOOTER/d; s/\(^\||\)"/\1/g; s/"\($\||\)/\1/g' csv 
HEADER
first, column|second "some random quotes" column|third ol' column

或者,使用GNU sed

sed -r '/FOOTER/d; s/(^|\|)"/\1/g; s/"($|\|)/\1/g' csv 

您还可以使用Perl:

$ perl -F"|" -lane 'next if /FOOTER/; s/^"|"$// for @F; print @F' csv 
HEADER
first, column|second some random quotes column|third ol' column

13

这也将起作用:

sed's / ^“ //; s /” |“ / | / g; s /”“ $ /” /'

例:

$ echo '"this"|" and "ths""|" and "|" this 2"|" also "this", "thi", "and th""' | 
sed 's/^"//; s/"|"/|/g; s/""$/"/'
this| and "ths"| and | this 2| also "this", "thi", "and th"

漂亮的版本

sed '
s/^"//
s/"|"/|/g
s/""$/"/
$d
'

1
这与页脚无关。
terdon

3
但这将删除最后一行,无论其内容如何。如果没有FOOTER,它将删除所需的数据。
terdon
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.