質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
bash

bash(Bourne-again-Shell)は sh(Bourne Shell)のインプリメンテーションに様々な機能が追加されたシェルです。LinuxやMac OS XではBashはデフォルトで導入されています。

sed

sedとは、POSIX環境のために作られたコマンドラインエディタです。sedは編集スクリプトの指示のもとに複数のファイルを編集し、標準出力にその結果を出力します。

AWK

AWKは、UNIX 上で開発されたプログラミング言語で、CSVファイルなどのテキストファイルの処理を目的にデザインされています。

Q&A

解決済

4回答

4455閲覧

1列のテキストファイルを分割して複数列にする方法

Gustave

総合スコア21

bash

bash(Bourne-again-Shell)は sh(Bourne Shell)のインプリメンテーションに様々な機能が追加されたシェルです。LinuxやMac OS XではBashはデフォルトで導入されています。

sed

sedとは、POSIX環境のために作られたコマンドラインエディタです。sedは編集スクリプトの指示のもとに複数のファイルを編集し、標準出力にその結果を出力します。

AWK

AWKは、UNIX 上で開発されたプログラミング言語で、CSVファイルなどのテキストファイルの処理を目的にデザインされています。

0グッド

0クリップ

投稿2016/06/06 08:39

編集2016/06/06 10:31

数百万行のテキストファイルがあり,コマンドラインから複数列に分割するための方法を探しています.
なお,何行刻みで分割するかはファイルによって違っています.

イメージとしては以下の様なtxtがあって(例:6行1列)

cat a.txt

a1
b1
c1
a2
b2
c2

これを,例えば以下の様なコマンドを叩けば3行刻みで,(3行2列)

./a.sh a.txt 3

a1 a2
b1 b2
c1 c2

と出来ると非常に幸せです.
会社のマシンで,Pythonなどが入っていないのです.
最悪の場合はCで書こうと思うのですが,
シェルスクリプト・awk, sedの範囲で,なにかいい知恵はないでしょうか.

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

ベストアンサー

私なら量が凄いので処理にSQLを使いたいですね。

手順としては、テーブルAを作り、a.txtから一行ずつ取り出して、何行目に何があったってそしてどんなグループで結合するかを保存していきます。
テーブルA
line_no | row_value | group_no
1 |a1 |1
2 |b1 |2
3 |c1 |3
4 |a2 |1
5 |b2 |2
6 |c2 |3

最初の読み込みではgroup_no以外を保存して、UPDATEで行数に応じてgroup_noを付けるほうが全体の行数を把握してから処理できて楽かもしれません。
なお、group_noを付けずにサブクエリで頑張ればできるかもしれませんが、遅そうなのでシンプルにgroup_noをつけたほうが良いと思います。

それでSQLで呼び出してファイルに書き込めばおしまいです。(↓はMySQLでテストしました)

SQL

1SELECT group_concat( row_value order by line_no separator ' ') as newrow FROM hoge.a group by group_no order by group_no ASC;

投稿2016/06/06 10:40

oskbt

総合スコア1895

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Gustave

2016/06/06 10:49

shellで頑張ってくださった以下の方には申し訳ありません. awk, sedでは無理そうで,Go言語などを入れるのもちょっと厳しい環境です. ちょっと表題とは違いますが,準標準といえるMysqlを使ったものをBAとさせて頂きました.
guest

0

awkです。

{ str1 = $1; getline str2 = $1; getline str3 = $1; getline str1 = str1 " " $1; getline str2 = str2 " " $1; getline str3 = str3 " " $1 print str1 print str2 print str3 }

とりあえず例示されたデータでは動くと思います。

投稿2016/06/06 09:42

takasima20

総合スコア7458

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

awkの部分だけ。Windows版gwakでしか確認していません。
即興で書いたのでバグっていたらごめんなさい。
行数は決め打ちしています(lcnt = 3)。
シェルのパラメタをawkに渡してあげてください。

方針としては、

  1. フィールドセパレータを改行にしてガッツリ読込み
  2. ENDで求める結果に合わせて表示

です。力技ですが、ちょっとしたツールならばこれでいいかと思います。
一度に読込むので、行数が膨大なものには向きませんが。

awk

1BEGIN { 2 FS = "\n" 3 rc = 0 4 lcnt = 3 5} 6{ data[rc++] = $0 } 7END { 8 rcnt = int(rc / lcnt) 9 for(i = 0; i < lcnt; i++) { 10 for (j = 0; j < rcnt; j++) { 11 output = data[i + lcnt * j] 12 if (j + 1 < rcnt) { 13 printf "%s ", output 14 } 15 else { 16 printf "%s\n", output 17 } 18 } 19 } 20}

投稿2016/06/06 09:41

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/06/06 09:58

最初の「数百万行」の記載を見落としていました。ちょっとこれでは無理ですねぇ。
Gustave

2016/06/06 10:28

なかなか手軽にできる方法がなくて困っています. ただ,会社のマシンでPythonなどをインストールできず, Cコンパイラは入ってるのですが,Cで書くのは辛いところです. 何か知恵がありましたら..
退会済みユーザー

退会済みユーザー

2016/06/06 10:42

私の環境(Windows)でも管理者権限なしの状態のマシンで、大量のテキスト処理(ログ解析なんですが)を必要としたときがあったのですが、その時は勉強がてらGo言語(ZIPアーカイブ版からインストール)を使ってプログラムを組みました。 個人的にはおススメだと思います。
guest

0

任意の行数で分割して列としてくっつけて行くわけですね?
ということは、戦略としては、飛ばし読みを指定した行数分繰り返すか、一旦指定行数でファイルを分割して、後でくっつけるかのどちらかになるかと思います。

指定行数でファイルを分割するAWKスクリプトは「ここ」にありましたので参照ください。

飛ばし読みだと、ファイルを指定した行数回頭からスキャンし直すことになります。スキャンの度に読み始める行を1つずつずらして指定行分飛ばして読み出せばできそうな気がします。
(例えば指定行数が3の場合、1回めのスキャンは1行目から読み始めて次は4,7,…と飛ばし読みして1行分を作って出力します。2回めのスキャンは2行目から読み始めて次は5,8,…と読み飛ばします。最後の3回めも同様です。)

なので、sedだけではちょっと難しいかと。AWKならできそうな気がします。

ただ、すいません、awkは最近全然いじってないので今すぐにはプログラムを示せません。^^;
上記のようなやり方で考えてみたらどうでしょうか?(またはawk使いのベテランが誰かいらっしゃると思うのでその人に託しますwww)

投稿2016/06/06 09:30

PineMatsu

総合スコア3579

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

PineMatsu

2016/06/06 09:52

これ「数百万行」って書いてあるけど、例えば100万行のファイルを3行で分割したら、1行あたり約33万個の文字が連なるので1行の文字列として限界を超えてしまう様に思います。実際には、100万行なら1000行で分割とかになるんでしょうね?
Gustave

2016/06/06 10:27

仰るとおりです. 割り切れないことは考えなくてOKです.
PineMatsu

2016/06/06 10:30

いや、割り切れるとかそういう事を問題にしてるわけじゃなくて、一行の文字数を問題にしてるんですが。
Gustave

2016/06/06 10:33

質問を空目しました.すいません. それなりに大きいサイズで分割することを考えているので,100万行なら1000~1万行で分割します. そのため,1行の文字列の限界は考えなくて構いません.
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問