1

ファイルから最初の1,000バイトを取得すると、Bashで一部の文字をすばやく置き換えることができます

$ cut -b-1000 get_video_info
muted=0&status=ok&length_seconds=24&endscreen_module=http%3A%2F%2Fs.ytimg.com%2F
yts%2Fswfbin%2Fendscreen-vfl4_CAIR.swf&plid=AATWGZfL-Ysy64Mp&sendtmp=1&view_coun
t=3587&author=hye+jeong+Jeong&pltype=contentugc&threed_layout=1&storyboard_spec=
http%3A%2F%2Fi1.ytimg.com%2Fsb%2FLHelEIJVxiE%2Fstoryboard3_L%24L%2F%24N.jpg%7C48
%2327%23100%2310%2310%230%23default%23cTWfBXjxZMDvzL5cyCgHdDJ3s_A%7C80%2345%2324
%2310%2310%231000%23M%24M%23m1lhUvkKk6sTnuyKXnPBojTIqeM%7C160%2390%2324%235%235%
231000%23M%24M%23r-fWFZpjrP1oq2uq_Y_1im4iu2I%7C320%23180%2324%233%233%231000%23M
%24M%23uGg7bth0q6XSYb8odKLRqkNe7ao&approx_threed_layout=1&allow_embed=1&allow_ra
tings=1&url_encoded_fmt_stream_map=fallback_host%3Dtc.v11.cache2.c.youtube.com%2
6quality%3Dhd1080%26sig%3D610EACBDE06623717B1DC2265696B473C47BD28F.98097DEC78411
95A074D6D6EBFF8B277F9C071AE%26url%3Dhttp%253A%252F%252Fr9---sn-q4f7dney.c.youtub
e.com%252Fvideoplayback%253Fms%253Dau%2526ratebypass%253Dyes%2526ipbits%253D8%25
26key%253Dyt1%2526ip%253D99.109.97.214%2

$ read aa < <(cut -b-1000 get_video_info)

$ time set "${aa//%/\x}"

real    0m0.025s
user    0m0.031s
sys     0m0.000s

ただし、10,000バイトを使用すると、大幅に遅くなります

$ read aa < <(cut -b-10000 get_video_info)

$ time set "${aa//%/\x}"

real    0m8.125s
user    0m8.127s
sys     0m0.000s

Greg Wooledgeの投稿を読みましたが、Bashパラメーターの展開が遅い理由についての説明がありません。

4

2 に答える 2

11

理由については、bashソースコードpat_substでこのコードの実装を確認できます。subst.c

文字列内の一致ごとに、文字列の長さは、C文字列としても、より高価なマルチバイト文字列としても、何度も(、、およびで)pat_substカウントmatch_patternされます。match_upatternこれにより、関数が必要以上に遅くなり、さらに重要なことに、複雑さが2次式になります。

これが、入力が大きいほど遅い理由です。これがきれいなグラフです。

シェル置換の2次ランタイム

回避策としては、を使用してくださいsed。文字列置換操作用に最適化される可能性が高くなります(ただし、GNU sedが任意の大きなバイトを処理する場合でも、POSIXは1行あたり8192バイトしか保証しないことに注意してください)。

于 2013-02-19T23:02:04.547 に答える
1

もともと、古いシェルや他のユーティリティは、この種の理由でファイル入力にLINE_MAX=2048を課していました。巨大な変数の場合、bashはそれらをメモリに駐車するのに問題はありません。ただし、置換には少なくとも2つの同時コピーが必要です。そして、多くのスラッシング:文字のグループが削除されると、文字列全体が書き直されます。何度も何度も。

これを目的としたツールがあります-sedは最高の選択肢です。bashは遠い2番目の選択肢です。sedはストリームで機能し、bashはメモリブロックで機能します。

別の選択肢:bashは拡張可能です-bashがそれを行うことを意図されていなかったときに、カスタムCコードを記述してうまく詰め込むことができます。

CFA Johnsonには、その方法に関する優れた記事があります。

ビルトインをロードする準備ができているもの:

http://cfajohnson.com/shell/bash/loadables/

DIYビルトインの説明:

http://cfajohnson.com/shell/articles/dynamically-loadable/

于 2013-02-19T22:42:46.640 に答える