linux sed 命令 - 在 csv 行的每一端添加字符串

linux sed command - adding string on every end of the line of csv

目前我在 ff CSV 数据上遇到问题。

COLUMN1,COLUMN2,COLUMN3,COLUMN4
apple1,apple2,apple3,apple4
banana1,banana2,banana3,
caimito1,"caimito21
caimito22","caimito31
caimito32",caimito4

看起来像这样:

╔══════════╦═══════════╦═══════════╦══════════╗
║ COLUMN1  ║  COLUMN2  ║  COLUMN3  ║ COLUMN4  ║
╠══════════╬═══════════╬═══════════╬══════════╬
║ apple1   ║ apple2    ║ apple3    ║ apple4   ║
║ banana1  ║ banana2   ║ banana3   ║          ║
║ caimito1 ║ caimito21 ║ caimito31 ║ caimito4 ║
║          ║ caimito22 ║ caimito32 ║          ║
╚══════════╩═══════════╩═══════════╩══════════╝

所以我的计划是添加 COLUMN5,它的每一行都有一个值 "FRUIT"。

使用的命令:

sed "1 s/$/,COLUMN5/g" FILE.csv | sed "2,$ s/$/,FRUIT/g" > OUTPUT.csv

输出:

╔══════════╦════════════════╦════════════════╦══════════╦═════════╗
║ COLUMN1  ║  COLUMN2       ║  COLUMN3       ║ COLUMN4  ║ COLUMN5 ║
╠══════════╬════════════════╬════════════════╬══════════╬═════════╣
║ apple1   ║ apple2         ║ apple3         ║ apple4   ║ FRUIT   ║
║ banana1  ║ banana2        ║ banana3        ║          ║ FRUIT   ║
║ caimito1 ║ caimito21FRUIT ║ caimito31FRUIT ║ caimito4 ║ FRUIT   ║
║          ║ caimito22      ║ caimito32      ║          ║         ║
╚══════════╩════════════════╩════════════════╩══════════╩═════════╝

有没有办法在不影响 "caimito" 行的情况下添加 "FRUIT"?

我也试过ff。命令,但没有成功。在“$”之前添加了“,”。

sed "1 s/$/,COLUMN5/g" FILE.csv | sed "2,$ s/,$/,FRUIT/g" > OUTPUT.csv

Sed 可能不是处理 csv 文件的正确工具,因为规则比看起来要复杂得多(这可能是可能的,但此类脚本通常很容易出错,等等)。但是,您可以使用 csvtools 来处理此问题:

file="FILE.csv"
nr=$(csvtool height $file)
ot=$(perl -e "print \"COLUMN5\n\";for$i(2..$nr){print \"FRUIT\n\";}")
echo "$ot" | csvtool paste "$file" -

脚本的工作原理如下:

  1. 首先我们用csvtool height,
  2. 计算行数
  3. 接下来我们通过打印 COLUMN5 后跟 n-1FRUIT.
  4. 来生成附加列
  5. 最后我们将该内容粘贴到文件的右侧。

编辑:我只看到了 csvtool 解决方案;它当然更实用。我留下这个解决方案主要是因为隐藏它和它的 Lovecraftian 美会很可惜。

好了,开始吧。这是在 sed 中执行此操作的一种方法:

sed ':a $!{ N; ba }; s/"[^"]*"/{&}/g; :b s/\({"[^"]*\)\n\([^"]*"}\)/~"~/g; tb; s/\n\|$/,FRUIT&/g; s/,FRUIT\(\n\|$\)/,COLUMN5/; :c s/\({"[^"]\)*~"~/\n/g; tc; s/{"\|"}/"/g' filename

这将是一段旅程。它的工作原理如下:

:a $!{ N; ba }                         # assemble the whole file in the
                                       # hold buffer

s/"[^"]*"/{&}/g                        # encase all "-enclosed fields in
                                       # {"..."} to make matching the beginning
                                       # and end separately possible.

:b                                     # jump mark for looping
s/\({"[^"]*\)\n\([^"]*"}\)/~"~/g   # replace the first newline in all
                                       # {"..."} fields with ~"~
tb                                     # loop until all were replaced

s/\n\|$/,FRUIT&/g                      # Put FRUIT at the end of all lines
s/,FRUIT\(\n\|$\)/,COLUMN5/          # Replace the first ,FRUIT with ,COLUMN5
                                       # The \(\n\|$\) bit is so that this
                                       # works with empty files (that only
                                       # have a header line)

:c                                     # Jump mark for looping
s/\({"[^"]\)*~"~/\n/g                # replace the first ~"~ in all {"..."}
                                       # fields with a newline
tc                                     # loop until all were replaced

s/{"\|"}/"/g                           # replace all {", "} markers with "
                                       # again.
sed '1 {
   s/$/,COLUMN5/
   b
   }
:load
/^\([^"]*"[^"]*"\)*[^"]*"[^"]*$/ {
   N
   b load
   }
s/$/,,,,/;s/^\(\([^,]*,\)\{4\}\).*/FRUIT/' YourFile
  • 在第 1 行添加 COLUMN5 比循环 (b)
  • 如果当前工作缓冲区上有打开的 ",请加载新行并重试此操作
  • 默认加4,
  • 将第 4 个第一组用 , 分开并添加 FRUIT
  • (周期)

posix 版本所以 --posix 在 GNU sed

对于 "valid" csv(1 行,所有参数由 , 分隔),只需删除负载循环部分