私は確かにこれはメモリにそれを行うよりも良いですが、ではないよsed
というr
パイプの反対側にあるすべてのそのINFILEの行と他のためにそのINFILEアウトEADSが交互にH
入力ラインと古いスペース...
cat <<\IN >/tmp/tmp
Row1,10
Row2,20
Row3,30
Row4,40
IN
</tmp/tmp sed -e 'i\
' -e 'r /tmp/tmp' |
sed -n '/./!n;h;N;/\n$/D;G;s/\n/ /;P;D'
出力
Row1,10 Row1,10
Row1,10 Row2,20
Row1,10 Row3,30
Row1,10 Row4,40
Row2,20 Row1,10
Row2,20 Row2,20
Row2,20 Row3,30
Row2,20 Row4,40
Row3,30 Row1,10
Row3,30 Row2,20
Row3,30 Row3,30
Row3,30 Row4,40
Row4,40 Row1,10
Row4,40 Row2,20
Row4,40 Row3,30
Row4,40 Row4,40
私はこれを別の方法でやった。メモリに一部を保存します-次のような文字列を保存します:
"$1" -
...ファイルの各行に対して。
pairs(){ [ -e "$1" ] || return
set -- "$1" "$(IFS=0 n=
case "${0%sh*}" in (ya|*s) n=-1;; (mk|po) n=+1;;esac
printf '"$1" - %s' $(printf "%.$(($(wc -l <"$1")$n))d" 0))"
eval "cat -- $2 </dev/null | paste -d ' \n' -- $2"
}
とても速いです。これcat
は、ファイル内の行と同じ数のファイルです|pipe
。パイプの反対側では、入力はファイル内の行と同じ回数だけファイル自体とマージされます。
case
ものは単なる移植性のためである- yash
とzsh
、スプリットに一つの要素を追加しながら、両方mksh
とposh
の両方を失う1。ksh
、dash
、busybox
、およびbash
によって印刷されたとしてゼロがあるとして多くの分野と正確にすべてのスプリットアウトprintf
。書かれているように、上記は私のマシン上の上記のシェルのすべてに対して同じ結果をレンダリングします。
ファイルが非常に長い場合、$ARGMAX
引数が多すぎる場合に問題が発生する可能性があり、その場合はxargs
同様に導入する必要があります。
出力が同一になる前に使用したのと同じ入力が与えられた場合。しかし、もし私が大きくなるとしたら...
seq 10 10 10000 | nl -s, >/tmp/tmp
それは私が前に使用したものとほぼ同じファイルを生成します (sans 'Row')とが、1000行になります。あなたはそれがどれくらい速いか自分で見ることができます:
time pairs /tmp/tmp |wc -l
1000000
pairs /tmp/tmp 0.20s user 0.07s system 110% cpu 0.239 total
wc -l 0.05s user 0.03s system 32% cpu 0.238 total
1000行では、シェル間でパフォーマンスにわずかなばらつきがあります- bash
常に最も遅いです-しかし、とにかく行うのはarg文字列を生成することだけであるため(の1000コピーfilename -
)を、効果は最小限です。zsh
上記のパフォーマンスの違いbash
は、ここでは100分の1秒です。
任意の長さのファイルで機能する別のバージョンを次に示します。
pairs2()( [ -e "$1" ] || exit
rpt() until [ "$((n+=1))" -gt "$1" ]
do printf %s\\n "$2"
done
[ -n "${1##*/*}" ] || cd -P -- "${1%/*}" || exit
: & set -- "$1" "/tmp/pairs$!.ln" "$(wc -l <"$1")"
ln -s "$PWD/${1##*/}" "$2" || exit
n=0 rpt "$3" "$2" | xargs cat | { exec 3<&0
n=0 rpt "$3" p | sed -nf - "$2" | paste - /dev/fd/3
}; rm "$2"
)
/tmp
奇妙なファイル名でハングアップしないように、セミランダムな名前で最初の引数へのソフトリンクを作成します。これは重要です。なぜなら、cat
の引数はを介してパイプ経由で渡されるからxargs
です。cat
出力が保存される<&3
一方、sed
p
そのファイル内の行が存在するように何回もrints最初の引数内のすべての行を-と、そのスクリプトは、パイプを介してそれに供給されます。再びpaste
その入力をマージしますが、今回-
はその標準入力とリンク名に対して再び2つの引数のみを取ります/dev/fd/3
。
最後に- /dev/fd/[num]
リンクは、Linuxシステムやその他の多くのシステムで動作するはずですが、名前付きパイプが作成されない場合はmkfifo
、代わりにそれを使用しても動作します。
最後に行うことはrm
、終了する前に作成するソフトリンクです。
私のシステムでは、このバージョンは実際にはまだ高速です。私はそれがより多くのアプリケーションを実行するけれども、彼らにすぐに彼らの議論を手渡し始めたからであると思う-それがそれらをすべて最初にスタックする前に。
time pairs2 /tmp/tmp | wc -l
1000000
pairs2 /tmp/tmp 0.30s user 0.09s system 178% cpu 0.218 total
wc -l 0.03s user 0.02s system 26% cpu 0.218 total