1

我有一个 15000 行的 CSV 文件。从列表中我想删除不需要的产品/制造商。我有一个制造商列表和源 CSV 文件。

我发现 sed 是合适的,但我在循环中徘徊。

while read line
do
    unwanted = $
sed "|"$unwanted|d" /home/arno/pixtmp/pixtmp.csv >/home/arno/pixtmp/pix-clean.c$
done < /home/bankey/shopimport/unwanted.txt

任何帮助表示赞赏。

输入文件:

耗材;Inktpatronen voor 打印机;Inkt voor 打印机;B0137790;HP;Pakket 2 inktpatronen No339 - Zwart + Papier Goodway - 80 g/m² - A4 - 500 vel;Dit pakket van 2 inktpatronen nr 339 zijn ontworpen voor uw HP 打印机 enleveren afdrukken van kwaliteit.;47.19;6.99;47.19;http://pan8.fotovista.com/dev/8/5/32150358/l_32150358.jpg;库存;0.2;0.11201;9.99;;C9504EE;0;;

4

3 回答 3

1

我将sed分两步使用:

  1. sed从不需要的信息创建脚本。
  2. 将创建的脚本应用到数据文件。

那可能是:

unwanted=/home/bankey/shopimport/unwanted.txt
datafile=/home/arno/pixtmp/pixtmp.csv
cleaned=/home/arno/pixtmp/pix-clean.csv

sed 's%.*%/,&,/d%' $unwanted > sed.script
sed -f sed.script  $datafile > $cleaned

rm -f sed.script

第一次调用sed只需将描述不需要的记录的每一行的内容替换为一个sed命令,该命令将删除它作为数据行中间的逗号分隔字段。如果您还必须在开头或结尾处理不需要的字段,那么您必须更加努力。如果可能嵌入斜杠、逗号、引号等,您还必须更加努力。第二次调用sed将第一次创建的脚本应用于数据文件,生成清理后的文件。

您可以通过确保脚本文件名是唯一的,并在进程中断时捕获脚本文件来改进它:

tmp=$(mktemp /tmp/script.XXXXXX)
trap "rm -f $tmp; exit 1" 0 1 2 3 13 15 # EXIT, HUP, INT, QUIT, PIPE, TERM

unwanted=/home/bankey/shopimport/unwanted.txt
datafile=/home/arno/pixtmp/pixtmp.csv
cleaned=/home/arno/pixtmp/pix-clean.csv

sed 's%.*%/,&,/d%' $unwanted > $tmp
sed -f $tmp $datafile > $cleaned

rm -f $tmp
trap 0  # Cancel the exit trap

使用 GNU sed,但不使用 Mac OS X (BSD) sed,您可以避免中间文件:

unwanted=/home/bankey/shopimport/unwanted.txt
datafile=/home/arno/pixtmp/pixtmp.csv
cleaned=/home/arno/pixtmp/pix-clean.csv

sed 's%.*%/,&,/d%' $unwanted |
sed -f - $datafile > $cleaned

这告诉第二个sed从标准输入读取它的脚本。如果您有bash版本 4.x(在 Mac OS X 上不是标准版本),则可以使用进程替换:

unwanted=/home/bankey/shopimport/unwanted.txt
datafile=/home/arno/pixtmp/pixtmp.csv
cleaned=/home/arno/pixtmp/pix-clean.csv

sed -f <(sed 's%.*%/,&,/d%' $unwanted) $datafile > $cleaned
于 2013-01-21T00:52:56.813 回答
0

sed不如awk. 例如,假设您的输入文件和不需要的术语列表是用空格分隔的,您可以简单地执行以下操作:

awk 'NR==FNR { a[$0]++ } NR != FNR && !a[$1]' undesired input

这将打印出文件“输入”文件,省略第一列与文件中的一行匹配的任何行undesired

于 2013-01-21T00:33:44.643 回答
0

您必须确保每个循环循环都将前一个循环的输出文件作为输入文件,否则您将继续用原始文件的内容减去最后一个不需要的记录来覆盖输出文件。

如果您的sed命令支持内联编辑(选项-i),您可以这样做:

cp /home/arno/pixtmp/pixtmp.csv /home/arno/pixtmp/pix-clean.csv
while read line; do
  sed -i "/$line/d" /home/arno/pixtmp/pix-clean.csv
done < /home/bankey/shopimport/unwanted.txt

否则,您必须自己处理临时文件:

cp /home/arno/pixtmp/pixtmp.csv /home/arno/pixtmp/pix-clean.csv
while read line; do
  sed "/$line/d" /home/arno/pixtmp/pix-clean.csv >/home/arno/pixtmp/pix-clean.c$
  mv -f /home/arno/pixtmp/pix-clean.c$ /home/arno/pixtmp/pix-clean.csv
done < /home/bankey/shopimport/unwanted.txt
于 2013-01-20T23:40:52.127 回答