更新了问题:http://pastebin.com/SrVC8PvW:
Sed文件 - csv2sql.sed
:
s|\([A-Z]*\),\([A-Z]*\),\([A-Za-z0-9’ ()\.\!-]*\),\([A-Za-z0-9’ ()\.\!-]*\),\([0-9]*\)|INSERT INTO `Schedule` (`ID`,`YEAR`,`NUMBER`,`TeamR1`,`TeamR2`, `TeamR3`, `TeamB1`, `TeamB2`, `TeamB3`) VALUES ('\1', '\2', '\3', '\4', '\5', '\6', '\7', '\8', '\9');|g
CSV文件(部分内容):
1,2015,0,57,3310,3676,624,3802,3481
控制台错误:
sed: file csv2sql.sed line 1: invalid reference \9 on `s` command's RHS
我有一个名为csv2sql.sed的SED文件,它将接收一个CSV文件并将其输出为SQL语法。我想运行该脚本,并在同一文件夹中有一个名为schedules.sql的 new sql文件。
如何解决我遇到的错误?
答案 0 :(得分:2)
这将是评论,但它在评论中的表达太复杂了,所以它就成了一个答案。
sed
脚本设置了5次捕获,然后尝试引用捕获1-9。错误消息告诉您无法引用未捕获的内容。
原始sed
脚本似乎是:
s|\([A-Z]*\),\([A-Z]*\),\([A-Za-z0-9' ()\.\!-]*\),\([A-Za-z0-9' ()\.\!-]*\),\([0-9]*\)|INSERT INTO `Schedule` (`ID`,`YEAR`,`NUMBER`,`TeamR1`,`TeamR2`, `TeamR3`, `TeamB1`, `TeamB2`, `TeamB3`) VALUES ('\1', '\2', '\3', '\4', '\5', '\6', '\7', '\8', '\9');|g
“匹配”部分是:
|\([A-Z]*\),\([A-Z]*\),\([A-Za-z0-9' ()\.\!-]*\),\([A-Za-z0-9' ()\.\!-]*\),\([0-9]*\)|
^ ^ ^ ^ ^
1 2 3 4 5
示例数据显示为以逗号分隔的9个整数。这似乎与使用的列标题没有多大相似之处,但这可能是一个单独的讨论。如果CSV数据足够简单,在字段中不包含逗号或单引号(在本例中),那么您可以更简单地处理它:
s|\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\)|INSERT … VALUES ('\1', '\2', '\3', '\4', '\5', '\6', '\7', '\8', '\9');|
如果您的sed
版本支持ERE(扩展正则表达式),则可以将其简化为:
s|([^,]*\),([^,]*\),([^,]*\),([^,]*\),([^,]*\),([^,]*\),([^,]*\),([^,]*\),([^,]*\)|INSERT … VALUES ('\1', '\2', '\3', '\4', '\5', '\6', '\7', '\8', '\9');|
您可能需要使用-r
(GNU sed
)或-E
(BSD sed
)来启用ERE。
这可以解决sed
脚本中的技术问题。这是一种处理数据的可怕方式。对于示例数据,您可以使用awk
来处理这些行:
awk -F, 'BEGIN { i1 = "INSERT INTO `Schedule` (`ID`,`YEAR`,`NUMBER`"
i2 = ",`TeamR1`,`TeamR2`, `TeamR3`, `TeamB1`,"
i3 = "`TeamB2`, `TeamB3`) VALUES"
}
NF==9 {printf "%s%s%s('%s','%s','%s','%s','%s','%s','%s','%s','%s');\n",
i1, i2, i3, $1, $2, $3, $4, $5, $6, $7, $8, $9 }
'
在awk
中还有许多其他方法可以解决这个问题,包括循环等。
如果您确实需要处理CSV数据,请使用能够理解CSV数据的语言。例如,Perl有Text::CSV(但它通常必须作为额外安装)并且Python已将其csv模块作为标准安装。这些都可以使管理变得更容易。
答案 1 :(得分:1)
假设您的sed文件是正确的(我怀疑),那么您将运行
sed -f csv2sql.sed xxx.dat > schedules.sql
其中xxx.dat是包含csv数据的文件。
将在您当前的工作目录中创建Schedules.sql。
答案 2 :(得分:0)
你可以这样跑
sed -f csv2sql.sed tes1.csv
CSV:
ABC,ABC,AbC9).,AbC9).,98
输出:
INSERT INTO `Schedule` (`F1`,`F2`,`F3`,`F4`,`F5`) VALUES ('ABC', 'ABC', 'AbC9).', 'AbC9).', '98');
csv2sql.sed看起来像这样
s|\([A-Z]*\),\([A-Z]*\),\([A-Za-z0-9’ ()\.\!-]*\),\([A-Za-z0-9’ ()\.\!-]*\),\([0-9]*\)|INSERT INTO `Schedule` (`F1`,`F2`,`F3`,`F4`,`F5`) VALUES ('\1', '\2', '\3', '\4', '\5');|g
答案 3 :(得分:0)
我不会使用sed
。很可能Python标准库中的 csv 模块可以解析您的输入,而您的编码远远少于您在{{1}中编写的任何内容。 }。
这是一个简单的程序,它会读取您所描述的CSV文件,假设您的标题行与列名列表相匹配(根据您希望它出现在SQL中的字面引用)并将其写入一系列INSERT INTO语句中,如您所述:
sed
只需要一点额外工作,您就可以添加对输入和输出文件名的命令行参数的支持,并将其转换为通用实用程序,以便为具有适当标题行的任何CSV生成SQL INSERT语句(您可以在其中指定表)使用命令行选项插入到其中。)
稍微省力一点就可以省略标题并让一些Python动态地从数据库中提取列名列表(通过任何Python DBAPI驱动程序执行#!python
# For Python version 2.x > 2.6
import csv, sys
form = 'INSERT INTO `Schedule` {0} VALUES ({1});\n'
if __name__ == '__main__':
num_args = len(sys.argv[1:])
if num_args < 1:
print >> sys.stderr, "Must supply input filename"
sys.exit(1)
with open(sys.argv[1], 'r') as infile:
reader = csv.reader(infile)
header = next(reader)
data = list()
for row in reader:
data.append(row)
with open('./csvdata.sql', 'w') as outfile:
for each in data:
outfile.write(form.format(', '.join(header), ', '.join(each)))
sometable SELECT * FROM
之类的查询并读取结果集对象WHERE 1=0
属性)。
为了说明简单,我只将它分成两个独立的循环...将.description
合并到第一个循环中以避免outfile.write()
,你可以处理任意大的文件常量内存开销。
直接添加SQL处理并弄清楚如何使用data.append
,您可以在一次传递中执行操作(CSV - &gt;您的SQL RDBMS),而无需中间的.sql文本文件。 (对此你也可能需要在CSV读取循环中添加一些类型处理)。但是,这可能比单个SQL INSERT语句的文本文件更有效地运行。 (这些Python DBAPI驱动程序的部分可能是平台本机C二进制文件,而不是通过.executemany()
中每行的Python调度执行。
这是适用于Python 3.x的脚本版本,并且实现了稍微改进的参数处理。这里输出文件是第一个参数,所有其他参数都是输入文件:
.executemany()
写(form.format(&#39;,&#39; .join(标题),&#39;,&#39; .join(每个))) 除了环境错误e: 打印(&#39;错误:%s:无法将结果写入%s&#39;%(e,sys.argv [1],file = sys.stderr) sys.exit(1)
此版本还在文件I / O读取输入错误周围添加了非常简单的异常处理,因为&#34;警告&#34;并将任何输出错误视为错误。