将MySQL命令行结果的输出格式更改为CSV

de90aj5v  于 2023-05-26  发布在  Mysql
关注(0)|答案(9)|浏览(193)

我想在命令行上从MySQL查询的输出中获取无标题CSV数据。我在与MySQL服务器不同的机器上运行这个查询,所以所有那些带有“INTO OUTFILE”的Google答案都不好。
所以我运行mysql -e "select people, places from things"。它输出的东西看起来像这样:

+--------+-------------+
| people | places      |
+--------+-------------+
|   Bill | Raleigh, NC |
+--------+-------------+

那可不好但是,嘿,看!如果我只是将它传递给 anything,它会将它变成一个制表符分隔的列表:

people  places
Bill    Raleigh, NC

这样更好-至少它是可编程解析的。但是我不想要TSV,我想要CSV,我不想要那个头。我可以用mysql <stuff> | tail -n +2去掉头部,但如果MySQL只是有一个省略它的标志,我想避免这个麻烦。我不能用逗号替换所有的标签,因为这不能处理带有逗号的内容。
那么,我如何让MySQL省略头部并以CSV格式给予数据呢?

k2arahey

k2arahey1#

作为部分答案:mysql -N -B -e "select people, places from things"
-N告诉它不要打印列标题。-B是“批处理模式”,使用制表符分隔字段。
如果制表符分隔的值不够,请参见this Stackoverflow Q&A

e7arh2l6

e7arh2l62#

上述解决方案仅在特殊情况下有效。你会陷入各种各样的麻烦,嵌入逗号,嵌入引号,其他事情,使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所要求的。

lztngnrs

lztngnrs3#

我写了my own command-line工具来处理这个问题。它类似于cut,除了它知道如何处理带引号的字段等。这个工具,与@Jimothy的答案配对,允许我从一个远程MySQL服务器获取一个无头CSV,我没有文件系统访问到我的本地机器上,使用这个命令:

$ mysql -N -e "select people, places from things" | csvm -i '\t' -o ','
Bill,"Raleigh, NC"

csvmaster on github

8mmmxcuj

8mmmxcuj4#

它是如何在客户端将结果保存为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"}}}'

需要做什么的逻辑解释

1.首先,让我们看看数据在RAW模式下的外观(使用--raw选项)。数据库和表分别为tdump3
您可以看到,由于值中放置了新行,从“new line”(第一行)开始的字段被拆分为三行。

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

1.在批处理模式下输出数据(不带--raw选项)-通过转义字符(如\<tab>new-lines)将每条记录更改为单行文本

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

1.以及CSV格式的数据输出
提示是将数据保存为带有转义字符的CSV格式。
方法是将mysql --batch产生的特殊实体(\t作为制表符,\\作为反斜线,\n作为换行符)转换为每个值(字段)的等效字节。然后整个值被"转义,并被"包围。顺便说一句,使用相同的字符进行转义和封闭可以稍微简化输出和处理,因为您没有两个特殊字符。出于这个原因,所有你必须做的值(从csv格式的Angular 来看)是改变""" whithin值。在更常见的方式中(分别使用转义和封闭\"),您必须首先将\更改为\\,然后将"更改为\"
以及命令的分步说明

# 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"} 
    }
}'
qvsjd97n

qvsjd97n5#

如何使用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,,
qmb5sa22

qmb5sa226#

mysqldump实用程序可以帮助您,基本上使用--tab选项,它是一个 Package 的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

6l7fqoea

6l7fqoea7#

mysql客户端可以检测输出fd,如果fd是S_IFFO(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以表格形式输出。

omtl5h9j

omtl5h9j8#

您可以使用spyql读取mysql的制表符分隔的输出并生成逗号分隔的CSV并关闭头写入:

$ mysql -e "SELECT 'Bill' AS people, 'Raleigh, NC' AS places" | spyql -Oheader=False "SELECT * FROM csv TO csv"
Bill,"Raleigh, NC"

spyql检测输入是否有标头以及定界符是什么。默认情况下,输出分隔符为逗号。如果需要,可以手动指定所有这些选项:

$ mysql -e "SELECT 'Bill' AS people, 'Raleigh, NC' AS places" | spyql -Idelimiter="'\t'" -Iheader=True -Odelimiter="," -Oheader=False "SELECT * FROM csv TO csv"
Bill,"Raleigh, NC"

我不会在mysql上关闭header写,因为spyql可以利用它,例如,如果你选择生成JSON而不是CSV:

$ mysql -e "SELECT 'Bill' AS people, 'Raleigh, NC' AS places" | spyql "SELECT * FROM csv TO json" 
{"people": "Bill", "places": "Raleigh, NC"}

或者,如果您需要引用列:

$ mysql -e "SELECT 'Bill' AS people, 'Raleigh, NC' AS places" | spyql -Oindent=2 "SELECT *, 'I am {} and I live in {}.'.format(people, places) AS message FROM csv TO json"
{
  "people": "Bill",
  "places": "Raleigh, NC",
  "message": "I am Bill and I live in Raleigh, NC."
}

免责声明:我是spyql的作者

lsmd5eda

lsmd5eda9#

如果你使用的是mysql客户端,你可以设置每个会话的resultFormat,例如:

mysql -h localhost -u root --result-format=json

mysql -h localhost -u root --vertical

在这里查看完整的参数列表。

相关问题