如何循环sed获取变量

时间:2013-01-20 22:44:12

标签: bash sed while-loop

我有一个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

感谢任何帮助。

Inputfile中:

耗材; 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打印机en leveren afdrukken van kwaliteit .; 47.19; 6.99; 47.19; http://pan8.fotovista.com/dev/8/5/32150358/l_32150358.jpg; in stock; 0.2; 0.11201; 9.99 ;; C9504EE; 0 ;;

3 个答案:

答案 0 :(得分:1)

我分两步使用sed

  1. 根据不需要的信息创建sed脚本。
  2. 将创建的脚本应用于数据文件。
  3. 那可能是:

    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
    

答案 1 :(得分: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

答案 2 :(得分:0)

sed不如awk。例如,假设您的输入文件和不受欢迎的术语列表以空格分隔,您可以执行以下操作:

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

这将打印出文件'input'文件,省略第一列与文件undesired中的一行匹配的任何行。