やりたいこと
入力 (標準入力)
stdin
A
B
C
D
E
F
出力 (標準出力)
stdout
A,B,C
D,E,F
結論
こちで回答したもの。
https://superuser.com/a/1738053/1722949
$ cat split.sh
#!/bin/bash -x
<input.txt pr -3tas,
<input.txt paste -d, - - -
<input.txt awk 'ORS=NR%3?",":"\n"'
<input.txt perl -pe'$.%3&&s/\n/,/'
<input.txt split -l3 --filter=paste\ -sd,
<input.txt perl -l0pe '$_.=$.%3?",":"\n"'
$ ./split.sh
+ pr -3tas,
A,B,C
D,E,F
+ paste -d, - - -
A,B,C
D,E,F
+ awk 'ORS=NR%3?",":"\n"'
A,B,C
D,E,F
+ perl '-pe$.%3&&s/\n/,/'
A,B,C
D,E,F
+ split -l3 '--filter=paste -sd,'
A,B,C
D,E,F
+ perl -l0pe '$_.=$.%3?",":"\n"'
A,B,C
D,E,F
解説
<input.txt
コマンドの標準入力に input.txt を流し込む (リダイレクト)。
リダイレクトはどこにあってもいい。
以下は等価 (サブプロセス起動とかで厳密には違う)
$ <input.txt command arg1 arg2
$ command <input.txt arg1 arg2
$ command arg1 <input.txt arg2
$ command arg1 arg2 <input.txt
$ cat input.txt | command arg1 arg2
pr -3tas,
-
pr: プリンタ出力用整形コマンド -
-3: 3段組みで -
-t: ヘッダなしで -
-a: 下方向ではなく横方向に (後述) -
-s,: カンマ区切りで
-a が無い場合、段組みの挙動となる
$ seq 9 | pr -3ts,
1,4,7
2,5,8
3,6,9
paste -d, - - -
paste はファイルを行単位に結合する。
今回はファイルとして標準入力 (-) を3回指定している。
paste
$ paste -d, a.txt b.txt c.txt
a1,b1,c1
a2,b2,c2
a3,b3,c3
a4,b4,c4
awk 'ORS=NR%3?",":"\n"'
awk の基本1 (基本形式)
$ awk '条件式{処理}' # 条件式 が 真 の場合 {処理} を実行する。
$ awk '{処理}' # 条件式 が暗黙的に 真 となる。
$ awk '条件式' # {処理} が暗黙的に {print $0} となる。<- 今回のパターン
awk の基本2 (代入演算子)
### 代入演算子 = は演算結果として代入後の結果を返す。
### 以下の () 内は最終的に a への代入結果の 4 に評価される。
$ awk 'BEGIN{print (a=2+2); print a}'
4
4
### 今回は ORS 変数への代入結果が "," or "\n" なので 条件式 は必ず 真 となる。
awk の基本3 (ORS)
### ORS 変数で print の改行記号が変更可能。
$ awk 'BEGIN{print 1; ORS="@"; print 2; ORS="/"; print 3}'
1
2@3/
- まとめ
- awk の基本形は
awk '条件式{処理}' -
条件式はORS=NR%3?",":"\n"(=引数全体) -
{処理}は{print $0}(暗黙的に指定) -
ORS変数への代入結果は","か"\n"なので条件式は必ず真 -
ORS変数を3行おきに"\n"、それ以外の行は","とし、printの改行記号を調整している
- awk の基本形は
perl -pe'$.%3&&s/\n/,/'
-
-p: 行ごとに暗黙的にprint($_)を実行-
$_: 入力行 (awk の$0)
-
-
-e: コマンドを指定 -
$.: 現在の行番号 (awk のNR) -
s/\n/,/: s 演算子で置換- 暗黙的に
$_ =~ s/\n/,/となり、$_が置換される
- 暗黙的に
-
&&で短絡評価され、$.%3が真の場合に限りs/\n/,/が実行される
split -l3 --filter=paste\ -sd,
split
### -l3: 3行ずつに分割
### --filter=command: 分割結果それぞれに対して command を実行
$ seq 6 | split -l3 --filter='cat -n'
1 1
2 2
3 3
1 4
2 5
3 6
paste
### -s なし: 行ごとに結合
$ paste -d, a.txt b.txt c.txt
a1,b1,c1
a2,b2,c2
a3,b3,c3
a4,b4,c4
### -s あり: ファイルごとに結合
$ paste -sd, a.txt b.txt c.txt
a1,a2,a3,a4
b1,b2,b3,b4
c1,c2,c3,c4
### 標準入力を1つのファイルとして読む
$ cat a.txt | paste -sd,
a1,a2,a3,a4
perl -l0pe '$_.=$.%3?",":"\n"'
-
-l0:print()の改行を無効化 -
-p: 行ごとに暗黙的にprint($_)を実行-
$_: 入力行 (awk の$0)
-
-
-e: 実行するコマンドを指定 -
.=: 文字列結合代入演算子 (python3 の+=) -
$.: 現在の行番号 (awk のNR)