在 CSV UNIX 中删除双引号之间的 \n

Posted

技术标签:

【中文标题】在 CSV UNIX 中删除双引号之间的 \\n【英文标题】:Removing \n in between double quotes in a CSV UNIX在 CSV UNIX 中删除双引号之间的 \n 【发布时间】:2013-12-10 18:30:23 【问题描述】:

我有一个由 IBM 从 Z/OS 更改数据交付生成的平面文件。数据中有新行或\n。我找到了一种使用 awk 命令替换其中大多数的方法,但似乎有一个小错误。如果有奇数个引号的行以引号结尾,则不会将\n 替换为空格。无论出于何种原因,我不得不循环两次才能获得其中的大部分。我留下了 1 条记录,其中仍有 \n。这是一个示例。

"2013-11-19 10:09:09","0","I","NOT SET   ","
simple string                            "

本质上需要:

"2013-11-19 10:09:09","0","I","NOT SET   ","simple string                            "

这是我正在使用的代码:

#For loop#
for a in 1 2 
do
  awk -F'"' '$NF""printf("%s ", $0);next1' $1 > $1.filter
  rm -f $1
  mv $1.filter $1
  echo $a
done

这个文件有大约 100k 条记录。它被 datastage 拾取,但看到 \n 抛出该记录,因为它认为下一行应该是新记录。

谢谢, 乔什

编辑:

我发现这个 Perl 命令可以做所有事情,但最终还是会遇到与上面相同的错误。

$ perl -p -le 's/\n+/ /g'

【问题讨论】:

只是好奇:你为什么使用$NF"" 而不仅仅是$NF 我不敢说实话。无论哪种方式,结果都是一样的。 【参考方案1】:

这是一种方法:

sed -n -e ':b; /^[^"]*"[^"]*\("[^"]*"[^"]*\)*$/  N; s/\
//; bb; ; p; '

在伪代码中

label foo:
  if we have an odd number of quotes:
    read and append the next line
    remove the line feed
    goto foo

print line

示例输出:

$ cat file
"2013-11-19 10:09:09","0","I","NOT SET   ","
simple string                    "
"normal data",42
"some other
string"
$ sed -n -e ':b; /^[^"]*"[^"]*\("[^"]*"[^"]*\)*$/  N; s/\
//; bb; ; p; ' < file
"2013-11-19 10:09:09","0","I","NOT SET   ","simple string                  "
"normal data",42
"some otherstring"
$ 

请注意,任何用反斜杠转义的引号都会破坏它("foo\"bar"),而用引号("foo""bar")转义的引号将起作用。确保您知道您使用的 CSV 方言。

【讨论】:

感谢您的回复。尝试使用您的上述代码时出现错误。 sed: 0602-417 The label :b; /^[^"]*"[^"]*\("[^"]*"[^"]*\)*$/ N; s/\//; bb; ; p; is greater than eight characters.【参考方案2】:

我研究了 glenn jackman 的建议,并在 python 中找到了解决方案。这是我使用 Python 编写的代码:

#!/usr/bin/python

import sys, csv, os

inputfile=sys.argv[1]
outputfile=sys.argv[1] + '.filter'
newtext=' '

print inputfile
print outputfile

with open(inputfile, "rb") as input:
  with open(outputfile, "wb") as output:
    w = csv.writer(output, delimiter=',', quotechar='"', quoting=csv.QUOTE_NONNUMERIC, lineterminator='\n')
    for record in csv.reader(input):
      w.writerow(tuple(s.replace("\n", newtext) for s in record))

os.rename(outputfile, inputfile)

感谢大家的帮助。希望有同样问题的人能找到这个。我对这个解决方案的唯一问题是它在所有字段周围添加了引号,包括空字段。

谢谢,乔希

编辑:

我能够使用 perl 快速删除所有相邻的双引号。

perl -pi -le 's/""//g' data

【讨论】:

【参考方案3】:

我会使用带有 CVS 解析器的语言。尝试解析当前行,如果有错误,加入下一行并重试:例如,with ruby​​:

ruby -rcsv -ne '
  chomp
  loop do
    begin
      row=CSV.parse_line($_)
      # if no error thrown, we have a parseable line
      puts row.inspect
      break
    rescue
      # grab the next line and try again
      $_ += gets
    end
  end
' << END
a,b,c,d,e
1,2,3,4,5
"2013-11-19 10:09:09","0","I","NOT SET   ","
simple string                            "
"a 1","b 2","c 3","d 4","e 5"
END
["a", "b", "c", "d", "e"]
["1", "2", "3", "4", "5"]
["2013-11-19 10:09:09", "0", "I", "NOT SET   ", "simple string                            "]
["a 1", "b 2", "c 3", "d 4", "e 5"]

【讨论】:

有没有可能是 python 的例子?这个 AIX 盒子没有 ruby​​。 感谢您的建议,我已经在python中开发了一个解决方案。【参考方案4】:
sed -n -e '/"/ 
   s/:/:d/g;s/\\"/:e/g
:b 
      /^\(\("[^"]*"\)*[^"]*\)*"\([^"]*\)$/  
      N
      s/\
//
      b b
      
   s/:e/\\"/g;s/:d/:g/
  
p' YourFile

在前面使用“\ 的翻译”。这使用了更多的 cpu,但通过转义“

【讨论】:

以上是关于在 CSV UNIX 中删除双引号之间的 \n的主要内容,如果未能解决你的问题,请参考以下文章

用其他东西替换或删除新行,但只能在 CSV 文件上使用 PHP 的单引号或双引号之间

从 .CSV 文件的数值中删除双引号和逗号

如果存在,则删除双引号之间的第一个逗号

正则表达式删除由双引号划定的 CSV 字段中的双引号

仅从数字中删除双引号

删除文本中所有双引号(python csv)