【问题标题】:unix - automatically determine field separator and record (EOL) separator?unix - 自动确定字段分隔符和记录(EOL)分隔符?
【发布时间】:2012-02-25 02:22:41
【问题描述】:

假设您有 20 个文件,您不会不查看每个文件,而是让脚本确定文件的格式。

即 bash findFileFormat direcName

然后循环遍历目录中的每个文件并打印出文件名以及它是否有分隔符(在这种情况下是逗号、管道或其他)或用 for 字段分隔符固定,然后是什么是记录分隔符。即CR、LF、Ctrl+Z字符等

我在想,因为某些文件可能在数据中有很多管道和逗号,它可以使用每行每个字符的计数来确定分隔符是什么 --> 如果这个过程没有产生一致的数量每行的字符可以安全地假设文件使用固定宽度的字段分隔符。

是否有可用于确定每个文件的这 2 位信息的命令或脚本?

【问题讨论】:

  • 无论您如何编写程序,您都必须设计一个非常复杂的类人逻辑来准确地执行您想要的操作。想想当您打开文件以确定格式时您的大脑所做的所有事情。有时它很容易发现(即您看到选项卡并且所有列都对齐)但有时它不会那么清楚。事实是,无论你怎么做,你能做的最好的事情就是给出一个“可能的最佳匹配”,给定一个可能的分隔符列表,但要准确地找到任何类型的文件的内容远非简单。

标签: linux bash shell unix scripting


【解决方案1】:

这是一个小的 Python 脚本,可以作为您需要的起点:

import sys

separators = [',', '|']
file_name = sys.argv[1]

def sep_cnt(line):
  return {sep:line.count(sep) for sep in separators}

with open(file_name, 'r') as inf:
  lines = inf.readlines()

cnts = [sep_cnt(line) for line in lines]
print(cnts)

def cnts_red(a, b):
  c = {}
  for k, v in a.iteritems():
    if v > 0 and v == b[k]:
      c[k] = v
  return c

final = reduce(cnts_red, cnts[1:], cnts[0])

if len(final) == 0:
  ftype = 'fixed'
else:
  ftype = 'sep by ' + str(final.iteritems().next()[0])

print(ftype)

将上面的 heur_sep.py 命名并在安全的地方运行它(例如 /tmp):

# Prepare
rm *.txt

# Commas
cat >f1.txt <<e
a,a,a,a
b,b,b,b
c,c,c,c
e

# Pipes
cat >f2.txt <<e
a|a|a|a
b|b|b|b
c|c|c|c
e

# Fixed width
cat >f3.txt <<e
1  2  3
1  2  3
1  2  3
e

# Fixed width with commas
cat >f4.txt <<e
1, 2  3
1  2, 3
1  2, 3,
e

for i in *.txt; do
  echo --- $i
  python heur_sep.py $i
done

您必须做更多的工作才能使其抵抗不同类型的错误,但应该是一个很好的起点。希望这可以帮助。

【讨论】:

    猜你喜欢
    • 2016-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-22
    • 2015-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多