web-dev-qa-db-ja.com

MySQLコマンドラインの結果の出力形式をCSVに変更する

コマンドラインでの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形式のデータを取得するにはどうすればよいですか?

56
spiffytech

私は 自分のコマンドライン ツールを書いてこれを処理しました。 cutに似ていますが、引用フィールドなどの処理方法がわかっている点が異なります。このツールと@Jimothyの回答を組み合わせることで、ファイルシステムにアクセスできないリモートMySQLサーバーからヘッダーレスCSVを取得できますこのコマンドを使用したローカルマシン:

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

githubのcsvmaster

13
spiffytech

部分的な答えとして:mysql -N -B -e "select people, places from things"

-Nは、列ヘッダーを出力しないように指示します。 -Bは「バッチモード」であり、タブを使用してフィールドを区切ります。

タブ区切りの値では不十分な場合は、 this Stackoverflow Q&A をご覧ください。

83
Jimothy

上記のソリューションは、特別な場合にのみ機能します。埋め込まれたコンマ、埋め込まれた引用符、一般的な場合にCSVを難しくするその他のことで、あらゆる種類のトラブルに巻き込まれます。

あなた自身を支持し、一般的な解決策を使用してください-それを正しく行えば、あなたはそれについて再び考える必要はないでしょう。非常に強力なソリューションの1つは、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が要求したものが生成されます。

10
Chris Johnson

非標準のツールを追加せずに、クライアント側で結果をCSVに保存する方法です。この例使用のみmysql clientおよびawk

1行:

 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」(最初の行)から始まるフィールドは、値に新しい行が配置されているために3行に分割されていることがわかります。

 mysql --skip-column-names --batch --raw -e 'select * from dump3' t 
 
 1行2新しい行
引用符"バックスラッシュ\ 2つの引用符" "2つのバックスラッシュ\\ 2つのタブ改行
フィールドの終わり
 
別の行1
  1. バッチモードでの出力データ--rawオプションなし)-\<tab>new-linesなどの文字をエスケープすることにより、各レコードが1行のテキストに変更されました
 mysql --skip-column-names --batch -e 'select * from dump3' t 
 
 1行2新しい行\ n引用符 "バックスラッシュ\\ 2つの引用符"" 2つのバックスラッシュ\\\\ 2つのタブ\ t\tnew line\nフィールドの終わり
別の行1特別な文字を含まない別の行の説明
  1. そしてCSV形式でのデータ出力

手がかりは、エスケープ文字を使用してデータをCSV形式で保存することです。

その方法は、mysql --batchが生成する特別なエンティティ(\tをタブとして\\をバックスラッシュとして、\nを改行として)を各値(フィールド)の同等のバイトに変換することです。次に、値全体が"でエスケープされ、"で囲まれます。ところで-エスケープと囲みに同じ文字を使用すると、2つの特殊文字がないため、出力と処理が簡単に簡素化されます。このため、値を(csv形式の観点から)行う必要があるのは、値を"から""に変更することだけです。より一般的な方法(それぞれ\"をエスケープして囲む)では、最初に\\\に変更し、次に"\"に変更する必要があります。

そして、コマンドのステップごとの説明

#ステップ2に示すように、1行の出力を生成します。
 mysql --skip-column-names --batch -e 'select * from dump3' t 
 
#mysqlがそのように生成するため、フィールドの区切り文字を設定します
 | awk -F '\ t' 
 
#これにより、mysqlデータのすべての行/レコードの繰り返しが開始されます-awk 
 '{
 
#フィールドセパレーターは空です。最初の出力フィールドの前にセパレーターを出力しないためです。
 sep = ""; 
 
-すべてのフィールドで反復し、フィールドをcsvの適切な値に変換する
 for(i = 1; i <= NF; i ++){
-注:\\ 2つのスラッシュはエスケープされているため、awkの\を意味します
 
-\ tを<tab> 
 gsub(/ \\ t /に対応するバイトに変更します、「\ t」、$ i); 
 
-\ nを新しい行に対応するバイトに変更します
 gsub(/ \\ n /、 "\ n"、$ i); 
 
-2つの\\を1つの\に変更
 gsub(/ \\\\ /、 "\\"、$ i); 
 
-値を文字どおり適切なCSVに変更-""を "" 
 gsub(/ "/、"\"\" "、$ i)に変更; [。 -セパレータは最初のフィールドが処理された後に設定されます-以前は必要ないため
 sep = "、"; 
 
-最後のフィールドが処理された後に新しい行を追加します-したがって、これはcsvレコードセパレーターを示します
 if(i == NF){printf "\ n"} 
} 
} '
9
Artur Siara

Sedを使用してはどうですか?ほとんどの(すべて?)Linux OSに標準で付属しています。

sed 's/\t/<your_field_delimiter>/g'

この例では、GNU sed(Linux)を使用します。 POSIX sed(AIX/Solaris)の場合、\tの代わりにリテラルTABを入力すると思います

例(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,,
2
xdaxdb

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が作成されます

2
b.b3rn4rd