【问题标题】:Remove spaces inbetween fields in a CSV file in UNIX在 UNIX 中删除 CSV 文件中的字段之间的空格
【发布时间】:2014-07-11 03:11:09
【问题描述】:

CSV 输入文件:

"18","Agent","To identify^M
","b5b553d2-81ab-4ec3-83e0-71ae3cf4afab","1"^M
"1078","Repeat","Identify
it has","0164f3eb-beeb-47dd-b9b9-9b762f430e14","1"^M
"621","Com Dot Com","Identify

","7fc9e73e-3470-4b31-8524-fcb97a4dadee","1"^M

在上面的输入文件中,我有 3 种不同类型的记录。

1) 第 18 条记录(前 2 行),即使它应该是 2 行,它也应该是 2 行。 ^M 错误地放置在第一行的末尾。

预期输出(从第一行删除^M并使其成为一行)

"18","Agent","To identify","b5b553d2-81ab-4ec3-83e0-71ae3cf4afab","1"^M

2) 第 1078 号记录(第 3 行和第 4 行) - 这里我在第 3 行末尾没有 ^M。我想将第 3 行和第 4 行合并为一行。

预期输出

"1078","Repeat","Identify it has ","0164f3eb-beeb-47dd-b9b99b762f430e14","1"^M

3) 第 621 号记录(第 4、5 和 6 行)- ^M 仅在行尾,但中间有一个空行。我想删除空白行并使其成为一行。

预期输出

"621","Com Dot Com","Identify","7fc9e73e-3470-4b31 8524fcb97a4dadee","1"^M

【问题讨论】:

  • 请使用formatting tools清晰地格式化您的问题。
  • 当然..谢谢..以后的帖子会做..
  • 我为您整理了格式,但您不认为您可以用更少的字段和更少的文本来证明您的问题。对于任何考虑帮助必须尝试通读所有内容以找出问题所在的人来说,这一切都非常令人反感。至少它阻止了我去思考它。
  • 删除了完整的输入并使其更短以便于阅读......

标签: linux bash csv awk sed


【解决方案1】:

使用 Ruby:

ruby -e 'require "csv"; CSV.parse(File.read(ARGV.shift)).each{ |e| e.map!{ |f| f.strip.gsub(/[[:space:]]+/, " ") }; puts CSV.generate_line(e, {:force_quotes => true}); }' csv_file

输出:

"18","Agent","To identify","b5b553d2-81ab-4ec3-83e0-71ae3cf4afab","1"
"1078","Repeat","Identify it has","0164f3eb-beeb-47dd-b9b9-9b762f430e14","1"
"621","Com Dot Com","Identify","7fc9e73e-3470-4b31-8524-fcb97a4dadee","1"

更易读的形式:

ruby -e 'require "csv"
    CSV.parse(File.read(ARGV.shift)).each{ |e|
        e.map!{ |f|
            f.strip.gsub(/[[:space:]]+/, " ")
        }
        puts CSV.generate_line(e, {:force_quotes => true})
    }' csv_file
  • Bash 的历史扩展可能会影响命令,因此您可以根据需要禁用它:shopt -u -o histexpand

脚本版本:

#!/usr/bin/env ruby
require 'csv'
CSV.parse(File.read(ARGV.shift)).each{ |e|
  e.map!{ |f|
    f.strip.gsub(/[[:space:]]+/, " ")
  }
  puts CSV.generate_line(e, {:force_quotes => true})
}

运行

ruby script.rb csv_file

请参阅Ruby-Doc.org 了解所有信息。

【讨论】:

    【解决方案2】:

    这可能有效:

    awk -F \",\" '
      /^[[:space:]]*$/ { next }
      {
        line = line $0
        if (split(line, a) == 10) {
          print line
          line = ""
        }
      }
    ' file
    

    我感觉还是会有一些问题(比如缺少空格)。

    【讨论】:

    • thanks ooga.. 它意外出现,所有 3 条记录都有“,作为第二行的开头。但它也可能有其他字符。我修改了第 1078 号记录。抱歉造成混淆。
    • 这适用于测试文件(5 条记录)。当我在真实文件上执行此操作时没有得到预期的输出..
    • @user3072054 因为我不知道“真实文件”是什么样的,所以我无能为力! :-) 如果文件太大无法在此处发布,您可以将其发布到wetransfer.com 并在评论中发布链接。
    • 这里是链接we.tl/D7Gy6mIa8V。错误记录18,32,51,56,90,232,252等
    • @user3072054 首先,这些行不像你说的那样以字符 ^M 结尾,所以我不确定你的意思。其次,为什么不手动修复线条?你会在一小时前完成的。
    【解决方案3】:

    将 GNU awk 用于多字符 RS:

    $ awk -v RS='^$' -v ORS= 'BEGIN{FS=OFS="\""} {for (i=2;i<=NF;i+=2) gsub(/\n/,"",$i) }1' file
    "18","Agent","To identify^M","b5b553d2-81ab-4ec3-83e0-71ae3cf4afab","1"^M
    "1078","Repeat","Identifyit has","0164f3eb-beeb-47dd-b9b9-9b762f430e14","1"^M
    "621","Com Dot Com","Identify","7fc9e73e-3470-4b31-8524-fcb97a4dadee","1"^M
    

    由于不清楚你是否真的有 control-M,所以我暂时将它们保留为字符“^M”。如果你有它们,只需 gsub() 将它们取出。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-11
      • 1970-01-01
      • 2013-01-04
      • 1970-01-01
      • 2013-08-29
      • 2013-12-10
      • 1970-01-01
      • 2017-08-24
      相关资源
      最近更新 更多