如何 运行 sed 命令接收 sed 文件并输出 sql 文件
How to run a sed command to take in a sed file and output a sql file
更新问题: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 ('', '', '', '', '', '', '', '', '');|g
CSV 文件(部分):
1,2015,0,57,3310,3676,624,3802,3481
控制台错误:
sed: file csv2sql.sed line 1: invalid reference on `s` command's RHS
我有一个名为 csv2sql.sed 的 SED 文件,它将接收一个 CSV 文件并将其输出为 SQL 语法。我想要 运行 脚本,并在同一文件夹中有一个名为 schedules.sql 的 new sql 文件。
如何解决我遇到的错误?
你可以运行这样
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 ('', '', '', '', '');|g
假设你的 sed 文件是正确的(我对此表示怀疑),那么你会 运行
sed -f csv2sql.sed xxx.dat > schedules.sql
其中 xxx.dat 是包含您的 csv 数据的文件。
Schedules.sql 将在您当前的工作目录中创建。
这本来是评论,但它太复杂了,无法再在评论中展示,所以它成为一个答案。
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 ('', '', '', '', '', '', '', '', '');|g
其中的 'matching' 部分是:
|\([A-Z]*\),\([A-Z]*\),\([A-Za-z0-9' ()\.\!-]*\),\([A-Za-z0-9' ()\.\!-]*\),\([0-9]*\)|
^ ^ ^ ^ ^
1 2 3 4 5
样本数据似乎是由逗号分隔的 9 个整数。这似乎与所使用的列标题不太相似,但这可能是一个单独的讨论。如果 CSV 数据足够简单,字段中不包含逗号或单引号(在本例中),那么您可以更简单地处理它:
s|\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\)|INSERT … VALUES ('', '', '', '', '', '', '', '', '');|
如果您的 sed
版本支持 ERE(扩展正则表达式),您可以将其简化为:
s|([^,]*\),([^,]*\),([^,]*\),([^,]*\),([^,]*\),([^,]*\),([^,]*\),([^,]*\),([^,]*\)|INSERT … VALUES ('', '', '', '', '', '', '', '', '');|
您可能需要使用 -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, , , , , , , , , }
'
在 awk
中还有许多其他方法可以处理此问题,包括循环等
如果你真的需要处理CSV数据,那就使用理解CSV数据的语言。例如,Perl 标准安装了 Text::CSV (but it usually has to be installed as an extra) and Python has its csv 模块。这些中的任何一个都会使其更易于管理。
我不会为此使用 sed
。 csv 标准库中的 csv 模块似乎很可能可以解析您的输入,而您的编码要少得多,而且比您要编写的任何内容都要健壮得多在 sed
.
这是一个简单的程序,它将读取您所描述的 CSV 文件,假设您有一个 header 行匹配您的列名列表(按字面意思引用,因为您希望它出现在您的 SQL) 并将其写入您所描述的一系列 INSERT INTO 语句中:
#!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)))
只需做一些额外的工作,您就可以为输入和输出文件名添加对命令行参数的支持,并将其转变为通用实用程序,用于为任何具有适当 [=56 的 CSV 生成 SQL INSERT 语句=] 行(您可以在其中指定使用命令行选项插入的 table)。
稍加努力,您可以省略 header 并使用一些 Python 从数据库中动态提取列名列表(执行 SELECT * FROM
sometableWHERE 1=0
通过任何 Python DBAPI driver 并读取结果集 objects .description
属性).
为了说明简单,我只将其分成两个单独的循环...将 outfile.write()
合并到第一个循环中以消除 data.append
,您可以处理任意大的文件常量内存开销。
直接添加 SQL 处理并弄清楚如何使用 .executemany()
并且您可以一次性执行操作(CSV -> 您的 SQL RDBMS),无需中介.sql 文本文件。 (这样做你可能还必须在 CSV 读取循环中添加一些类型处理)。但是,这可能比单个 SQL INSERT 语句的文本文件更有效。 (例如,这些 Python DBAPI driver 的部分可能在平台本机 C 二进制文件中,而不是通过 Python 为 .executemany()
中的每一行分派来执行)。
这是 Python 3.x 的脚本 suitable 的一个版本,并实现了稍微改进的参数处理。这里输出文件是第一个参数,所有其他参数都是输入文件:
#!python
#!/usr/bin/env python3
## Python 3.x
import csv, sys
usage='%s outfile infile [infile2 ...]' % sys.argv[0]
form = 'INSERT INTO `Schedule` {0} VALUES ({1});\n'
if __name__ == '__main__':
num_args = len(sys.argv[1:])
if num_args < 1:
print ("Must supply input filename", file=sys.stderr)
sys.exit(1)
data = list()
for each in sys.argv[2:]:
try:
with open(each, 'r') as infile:
reader = csv.reader(infile)
header = next(reader)
for row in reader:
data.append(row)
except EnvironmentError as e:
print('Warning %s: unable to read data from %s' % (e, each), file=sys.stderr)
try:
with open(sys.argv[1], 'w') as outfile:
for each in data:
outfile.
write(form.format(', '.join(header), ', '.join(each)))
除了 EnvironmentError 为 e:
打印('Error: %s: unable to write results to %s' % (e, sys.argv[1], 文件=sys.stderr)
sys.exit(1)
此版本还在文件 I/O 周围添加了非常简单的异常处理,将输入错误读取为 "Warnings" 并将任何输出错误读取为错误。
更新问题: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 ('', '', '', '', '', '', '', '', '');|g
CSV 文件(部分):
1,2015,0,57,3310,3676,624,3802,3481
控制台错误:
sed: file csv2sql.sed line 1: invalid reference on `s` command's RHS
我有一个名为 csv2sql.sed 的 SED 文件,它将接收一个 CSV 文件并将其输出为 SQL 语法。我想要 运行 脚本,并在同一文件夹中有一个名为 schedules.sql 的 new sql 文件。
如何解决我遇到的错误?
你可以运行这样
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 ('', '', '', '', '');|g
假设你的 sed 文件是正确的(我对此表示怀疑),那么你会 运行
sed -f csv2sql.sed xxx.dat > schedules.sql
其中 xxx.dat 是包含您的 csv 数据的文件。
Schedules.sql 将在您当前的工作目录中创建。
这本来是评论,但它太复杂了,无法再在评论中展示,所以它成为一个答案。
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 ('', '', '', '', '', '', '', '', '');|g
其中的 'matching' 部分是:
|\([A-Z]*\),\([A-Z]*\),\([A-Za-z0-9' ()\.\!-]*\),\([A-Za-z0-9' ()\.\!-]*\),\([0-9]*\)|
^ ^ ^ ^ ^
1 2 3 4 5
样本数据似乎是由逗号分隔的 9 个整数。这似乎与所使用的列标题不太相似,但这可能是一个单独的讨论。如果 CSV 数据足够简单,字段中不包含逗号或单引号(在本例中),那么您可以更简单地处理它:
s|\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\),\([^,]*\)|INSERT … VALUES ('', '', '', '', '', '', '', '', '');|
如果您的 sed
版本支持 ERE(扩展正则表达式),您可以将其简化为:
s|([^,]*\),([^,]*\),([^,]*\),([^,]*\),([^,]*\),([^,]*\),([^,]*\),([^,]*\),([^,]*\)|INSERT … VALUES ('', '', '', '', '', '', '', '', '');|
您可能需要使用 -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, , , , , , , , , }
'
在 awk
中还有许多其他方法可以处理此问题,包括循环等
如果你真的需要处理CSV数据,那就使用理解CSV数据的语言。例如,Perl 标准安装了 Text::CSV (but it usually has to be installed as an extra) and Python has its csv 模块。这些中的任何一个都会使其更易于管理。
我不会为此使用 sed
。 csv 标准库中的 csv 模块似乎很可能可以解析您的输入,而您的编码要少得多,而且比您要编写的任何内容都要健壮得多在 sed
.
这是一个简单的程序,它将读取您所描述的 CSV 文件,假设您有一个 header 行匹配您的列名列表(按字面意思引用,因为您希望它出现在您的 SQL) 并将其写入您所描述的一系列 INSERT INTO 语句中:
#!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)))
只需做一些额外的工作,您就可以为输入和输出文件名添加对命令行参数的支持,并将其转变为通用实用程序,用于为任何具有适当 [=56 的 CSV 生成 SQL INSERT 语句=] 行(您可以在其中指定使用命令行选项插入的 table)。
稍加努力,您可以省略 header 并使用一些 Python 从数据库中动态提取列名列表(执行 SELECT * FROM
sometableWHERE 1=0
通过任何 Python DBAPI driver 并读取结果集 objects .description
属性).
为了说明简单,我只将其分成两个单独的循环...将 outfile.write()
合并到第一个循环中以消除 data.append
,您可以处理任意大的文件常量内存开销。
直接添加 SQL 处理并弄清楚如何使用 .executemany()
并且您可以一次性执行操作(CSV -> 您的 SQL RDBMS),无需中介.sql 文本文件。 (这样做你可能还必须在 CSV 读取循环中添加一些类型处理)。但是,这可能比单个 SQL INSERT 语句的文本文件更有效。 (例如,这些 Python DBAPI driver 的部分可能在平台本机 C 二进制文件中,而不是通过 Python 为 .executemany()
中的每一行分派来执行)。
这是 Python 3.x 的脚本 suitable 的一个版本,并实现了稍微改进的参数处理。这里输出文件是第一个参数,所有其他参数都是输入文件:
#!python
#!/usr/bin/env python3
## Python 3.x
import csv, sys
usage='%s outfile infile [infile2 ...]' % sys.argv[0]
form = 'INSERT INTO `Schedule` {0} VALUES ({1});\n'
if __name__ == '__main__':
num_args = len(sys.argv[1:])
if num_args < 1:
print ("Must supply input filename", file=sys.stderr)
sys.exit(1)
data = list()
for each in sys.argv[2:]:
try:
with open(each, 'r') as infile:
reader = csv.reader(infile)
header = next(reader)
for row in reader:
data.append(row)
except EnvironmentError as e:
print('Warning %s: unable to read data from %s' % (e, each), file=sys.stderr)
try:
with open(sys.argv[1], 'w') as outfile:
for each in data:
outfile.
write(form.format(', '.join(header), ', '.join(each))) 除了 EnvironmentError 为 e: 打印('Error: %s: unable to write results to %s' % (e, sys.argv[1], 文件=sys.stderr) sys.exit(1)
此版本还在文件 I/O 周围添加了非常简单的异常处理,将输入错误读取为 "Warnings" 并将任何输出错误读取为错误。