10
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

標準入力をN行ずつカンマ区切りにする

Last updated at Posted at 2022-08-20

やりたいこと

入力 (標準入力)

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 の改行記号を調整している

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)
10
7
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?