コマンドラインでの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形式のデータを取得するにはどうすればよいですか?
私は 自分のコマンドライン ツールを書いてこれを処理しました。 cut
に似ていますが、引用フィールドなどの処理方法がわかっている点が異なります。このツールと@Jimothyの回答を組み合わせることで、ファイルシステムにアクセスできないリモートMySQLサーバーからヘッダーレスCSVを取得できますこのコマンドを使用したローカルマシン:
$ mysql -N -e "select people, places from things" | csvm -i '\t' -o ','
Bill,"Raleigh, NC"
部分的な答えとして:mysql -N -B -e "select people, places from things"
-N
は、列ヘッダーを出力しないように指示します。 -B
は「バッチモード」であり、タブを使用してフィールドを区切ります。
タブ区切りの値では不十分な場合は、 this Stackoverflow Q&A をご覧ください。
上記のソリューションは、特別な場合にのみ機能します。埋め込まれたコンマ、埋め込まれた引用符、一般的な場合に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が要求したものが生成されます。
非標準のツールを追加せずに、クライアント側で結果を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 "} }} '
何をする必要があるかの論理的な説明
まず、RAWモードでのデータの表示方法(--raw
オプションを使用)を参照してください。データベースとテーブルはそれぞれt
とdump3
です
「new line」(最初の行)から始まるフィールドは、値に新しい行が配置されているために3行に分割されていることがわかります。
mysql --skip-column-names --batch --raw -e 'select * from dump3' t 1行2新しい行 引用符"バックスラッシュ\ 2つの引用符" "2つのバックスラッシュ\\ 2つのタブ改行 フィールドの終わり 別の行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特別な文字を含まない別の行の説明
手がかりは、エスケープ文字を使用してデータを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"} } } '
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,,
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
が作成されます