【问题标题】:vim & csv file: put header info into a new columnvim & csv 文件:将标题信息放入新列
【发布时间】:2009-05-15 07:04:44
【问题描述】:

我有大量如下所示的 csv 文件:


xxxxxxxxx
xxxxx
出货,YD564n
xxxxxxxxx
xxxxx

1,RR1760
2、HI3503
3、HI4084
4、HI1824


我需要让它们看起来像下面这样:


xxxxxxxxx
xxxxx
出货,YD564n
xxxxxxxxx
xxxxx

YD564n,1,RR1760
YD564n,2,HI3503
YD564n,3,HI4084
YD564n,4,HI1824


YD564n 是一个货件编号,每个 csv 文件都不同。但它总是紧跟在“Shipment”之后。

我可以使用哪些 vim 命令?

【问题讨论】:

    标签: regex vim csv replace copy-paste


    【解决方案1】:

    在正常模式下在一个文件中键入以下内容:

    qqgg/^Shipment,<CR>ww"ay$}j:.,$s/^/<C-R>a,<CR>q
    

    注意&lt;CR&gt; 是 ENTER 键,&lt;C-R&gt; 是 CTRL-R。

    这将更新该文件并记录寄存器 q 中的命令。

    然后在其他文件中键入@q(也在正常模式下)。 (这将播放寄存器 q)

    【讨论】:

      【解决方案2】:

      您可以使用宏来执行此操作,并将其应用于多个文件。

      这是一个例子。按原样输入以下内容:

      3gg$"ayiw:6,$s/^/<C-R>a/<CR>:w<CR>:bn<CR>
      

      现在看起来很可怕。让我看看能不能解释清楚一点。

      3gg$ : 转到第三行末尾。

      "ayiw:将最后一个单词复制到寄存器a

      :6,$s/^/&lt;C-R&gt;a/&lt;CR&gt; : 从第 6 行开始的每一行中,将寄存器 a 中的内容替换为开头。

      :w&lt;CR&gt;:bn&lt;CR&gt;:保存并转到下一个缓冲区。

      现在您可以将其映射到一个键,通过

      :nnoremap <C-A> 3gg$"ayiw:6,$s/^/<C-R>a/<CR>:w<CR>:bn<CR>
      

      如果你有 200 个 csv 文件,你打开 vim

      vim *.csv
      

      然后

      200<C-A>
      

      你在那里输入 Ctrl-A,应该就完成了。

      也就是说,使用适当的脚本语言执行此操作肯定会更舒服,它会更直接。

      【讨论】:

        【解决方案3】:

        这可以作为 Perl 单行来完成:

        perl -i.bak -e' $c = do {local $/; <>};
                        ($n) = ($c =~ /Shipment,(\w+)/);
                        $c =~ s/^(\d+,)/$n,$1/gm;
                        print $c' shipment.csv
        

        这会将shipment.csv 的内容读入$c,将货件ID 提取到$n,并在每个CSV 行前面加上货件编号。该文件将在原地修改,并将备份保存到shipment.csv.bak

        要在 Vim 中执行此操作,请将其调整为过滤器:

        :%!perl -e' $c = do {local $/; <>}; ($n) = ($c =~ /Shipment,(\w+)/); $c =~ s/^(\d+,)/$n,$1/gm; print $c'
        

        【讨论】:

          【解决方案4】:

          好吧,不要抨击我,但是...你可以考虑:不要在 vim 中这样做!!

          这是脚本语言的经典用法示例。 学习基本的 python、perl 或 ruby​​ 教程。解决方案将 在里面。

          这方面的正则表达式可能不会太难,而且它在 vim 中是可行的。 但是那里有更简单的选择。 还有更灵活的。

          【讨论】:

            【解决方案5】:

            为什么是 vim?

            试试这个 shell 脚本:

            #!/bin/sh
            
            input=$1
            
            shipment=`grep Shipment $input|awk -F, '{print $2}'`
            
            mv $input $input.orig
            
            sed -e "s/^\([0-9]\)/$shipment,\1/" $input.orig > $input
            

            您可以遍历特定文件:

            for input in *.txt
            do
                script.sh $i
            done
            

            【讨论】:

              【解决方案6】:

              我也认为这不太适合 vim,在 Bash 中怎么样?

              FILENAME='filename.csv' && SHIPMENT=`grep Shipment $FILENAME | sed 's/^Shipment,//'` && cat $FILENAME | sed "s/^[0-9]/$SHIPMENT,&/" > $FILENAME
              

              【讨论】:

                猜你喜欢
                • 2021-07-20
                • 1970-01-01
                • 2013-10-04
                • 2022-12-24
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2018-03-25
                相关资源
                最近更新 更多