我想在命令行上从查询输出中获取无头CSV数据。我在与MySQL服务器不同的机器上运行此查询,因此所有使用“INTO OUTFILE”的Google答案都不好。
所以我运行mysql -e "select people, places from things"
。这会输出看起来像这样的东西:
+--------+-------------+
| people | places |
+--------+-------------+
| Bill | Raleigh, NC |
+--------+-------------+
嗯,这不好。但是,嘿,看!如果我只是将它传递给任何,它会把它变成一个以制表符分隔的列表:
people places
Bill Raleigh, NC
那更好 - 至少它是以编程方式解析的。但我不想要TSV,我想要CSV,而且我不想要那个标题。我可以用mysql <stuff> | tail -n +2
删除标题,但如果MySQL只有一个标志可以省略它,那就太麻烦了。而且我不能用逗号替换所有标签,因为它不能处理带有逗号的内容。
那么,我怎样才能让MySQL省略标题并以CSV格式提供数据?
答案 0 :(得分:80)
作为部分答案:mysql -N -B -e "select people, places from things"
-N
告诉它不要打印列标题。 -B
是“批处理模式”,并使用制表符分隔字段。
如果制表符分隔值不够,请参阅this Stackoverflow Q&A。
答案 1 :(得分:13)
我最后编写my own command-line工具来处理这件事。它类似于cut
,除了它知道如何处理引用字段等。这个工具与@Jimothy的答案配对,允许我从远程MySQL服务器获取无头CSV,我没有文件系统访问我的使用此命令的本地计算机:
$ mysql -N -e "select people, places from things" | csvm -i '\t' -o ','
Bill,"Raleigh, NC"
答案 2 :(得分:9)
如果没有其他非标准工具,可以在客户端将结果保存为CSV。
此示例仅使用 mysql
客户端和awk
。
<强>单行:强>
mysql --skip-column-names --batch -e 'select * from dump3' t | awk -F'\t' '{ sep=""; for(i = 1; i <= NF; i++) { gsub(/\\t/,"\t",$i); gsub(/\\n/,"\n",$i); gsub(/\\\\/,"\\",$i); gsub(/"/,"\"\"",$i); printf sep"\""$i"\""; sep=","; if(i==NF){printf"\n"}}}'
需要做什么的逻辑解释
首先,让我们看一下 RAW模式下数据的样子(带--raw
选项)。数据库和表分别是t
和dump3
您可以看到从“新行”(在第一行)开始的字段由于在行中放置了新行而被拆分为三行。
mysql --skip-column-names --batch --raw -e 'select * from dump3' t one line 2 new line quotation marks " backslash \ two quotation marks "" two backslashes \\ two tabs new line the end of field another line 1 another line description without any special chars
--raw
选项) - 通过转发\
<tab>
和{{}等字符,将每条记录更改为单行文字{1}} mysql --skip-column-names --batch -e 'select * from dump3' t one line 2 new line\nquotation marks " backslash \\ two quotation marks "" two backslashes \\\\ two tabs\t\tnew line\nthe end of field another line 1 another line description without any special chars
线索是使用转义字符以CSV格式保存数据。
这样做的方法是将new-lines
生成(mysql --batch
作为标签\t
作为反向缩进,将\\
作为换行符)的特殊实体转换为每个值的等效字节(领域)。
然后整个值由\n
转义,并由"
括起来。
顺便说一句 - 使用相同的字符进行转义和封闭可以轻松简化输出和处理,因为您没有两个特殊字符。
因此,您需要处理的所有值(从csv格式的角度来看)都是将值"
更改为"
。以更常见的方式(分别转义和封闭""
和\
),您必须先将"
更改为\
,然后将\\
更改为{{ 1}}。
命令'一步一步解释:
# we produce one-line output as showed in step 2. mysql --skip-column-names --batch -e 'select * from dump3' t # set fields separator to because mysql produces in that way | awk -F'\t' # this start iterating every line/record from the mysql data - standard behaviour of awk '{ # field separator is empty because we don't print a separator before the first output field sep=""; -- iterating by every field and converting the field to csv proper value for(i = 1; i <= NF; i++) { -- note: \\ two shlashes below mean \ for awk because they're escaped -- changing \t into byte corresponding to <tab> gsub(/\\t/, "\t",$i); -- changing \n into byte corresponding to new line gsub(/\\n/, "\n",$i); -- changing two \\ into one \ gsub(/\\\\/,"\\",$i); -- changing value into CSV proper one literally - change " into "" gsub(/"/, "\"\"",$i); -- print output field enclosed by " and adding separator before printf sep"\""$i"\""; -- separator is set after first field is processed - because earlier we don't need it sep=","; -- adding new line after the last field processed - so this indicates csv record separator if(i==NF) {printf"\n"} } }'
答案 3 :(得分:9)
以上解决方案仅适用于特殊情况。嵌入式逗号,嵌入式引号以及在一般情况下使CSV变硬的其他因素,你会遇到各种各样的麻烦。
帮自己一个忙,并使用一般解决方案 - 做得对,你再也不用考虑了。一个非常强大的解决方案是csvkit
命令行实用程序 - 通过Python可用于所有操作系统。通过pip install csvkit
安装。这将为您提供正确的CSV数据:
mysql -e "select people, places from things" | csvcut -t
生成以逗号分隔的数据,标题仍然存在。要删除标题行:
mysql -e "select people, places from things" | csvcut -t | tail -n +2
产生OP要求的内容。
答案 4 :(得分:2)
mysqldump
实用程序可以帮助您,基本上使用--tab
选项它包含SELECT INTO OUTFILE
语句。
示例:
mysqldump -u root -p --tab=/tmp world Country --fields-enclosed-by='"' --fields-terminated-by="," --lines-terminated-by="\n" --no-create-info
这将创建csv格式的文件/tmp/Country.txt
答案 5 :(得分:2)
使用sed怎么样?它是大多数(所有?)Linux操作系统的标准配置。
sed 's/\t/<your_field_delimiter>/g'
。
此示例使用GNU sed(Linux)。对于POSIX sed(AIX / Solaris),我相信你会输入一个文字TAB而不是\t
示例(用于CSV输出):
#mysql mysql -B -e "select * from user" | while read; do sed 's/\t/,/g'; done
localhost,root,,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,,,,,0,0,0,0,,
localhost,bill,*2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,,,,,0,0,0,0,,
127.0.0.1,root,,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,,,,,0,0,0,0,,
::1,root,,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,Y,,,,,0,0,0,0,,
%,jim,*2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,,,,,0,0,0,0,,
答案 6 :(得分:1)
mysql 客户端可以检测输出 fd,如果 fd 是 S_IFIFO(pipe) 则不输出 ASCII TABLES,如果 fd 是字符设备(S_IFCHR)则输出 ASCII TABLES。
您可以使用 --table 强制输出 ASCII 表,例如:
$mysql -t -N -h127.0.0.1 -e "select id from sbtest1 limit 1" | cat
+--------+
| 100024 |
+--------+
-t, --table 以表格格式输出。
答案 7 :(得分:0)
如果您使用的是mysql客户端,则可以设置每个会话的resultFormat,例如
mysql -h localhost -u root --resutl-format=json
或
mysql -h localhost -u root --vertical
查看参数here的完整列表。