純粋なbashを使用してファイル内の文字列を一致させるには?

純粋なbashを使用してファイル内の文字列を一致させるには?

だからファイルの文字列/または単語を一致させたいのですがいいえ外部ツール(grepなどsed)を使用してください。純粋なbashだけを使用してください。

本質的に私は次のようなものが欲しい。

grep "string" file

または

grep -w "string" file

純粋なbashで。

PS:私はファイル内の正確な文字列を一致させることに興味があるので(改行の有無にかかわらず)完全な正規表現のサポートは必要ありません(他の外部ツールがそれをサポートできます)。

答え1

できます。しかし、これは非常に非常に悪い考えです。grep特定のシェル(Bash)の機能に依存するため、次のものよりはるかに遅くなります(数十倍遅い)。

これにより、次のように、最初の引数として指定された正規表現パターンに一致する行が印刷されますgrep pattern

#!/bin/bash -

regexp="$1"
ret=1
while IFS= read -r line || [ -n "$line" ]; do
  if [[ $line =~ $regexp ]]; then
    printf '%s\n' "$line"
    ret=0
  fi
done
exit "$ret"

別の名前で保存しfoo.bashて、次のように実行してください。

foo.bash pattern < inputFile

または、標準sh構文を使用して正規表現の代わりに固定文字列を検索します。

#!/bin/sh -

string="$1"
ret=1
while IFS= read -r line || [ -n "$line" ]; do
  case $line in
    (*"$string"*)
      printf '%s\n' "$string"
      ret=0
  esac
done
exit "$ret"

(のようなものを得るためprintfにに置き換えてください。)exit 0grep -q

どれくらい遅いかを知らせるために、10001行だけのファイルを作成しました。最初の5000行はfoo、次に1行bar、もう1つの5000行は次のとおりですfoo

perl -e 'print "foo\n" x 5000; print "bar\n"; print "foo\n" x 5000;' > file

grepさて、上記のスクリプトのタイミングを比較してみましょう。

$ time grep bar < file
bar

real    0m0.002s
user    0m0.002s
sys     0m0.000s

$ time ./foo.bash bar < file
bar

real    0m0.116s
user    0m0.101s
sys     0m0.016s

ご覧のとおり、ファイルサイズが小さくても差が目立つ。より実用的なスクリプトを使用しようとすると、スクリプトにほとんど耐えられない時間がかかります。

$ perl -e 'print "foo\n" x 500000; print "bar\n"; print "foo\n" x 500000;' > file


$ time grep bar < file
bar

real    0m0.004s
user    0m0.000s
sys     0m0.004s


$ time ./foo.bash bar < file
bar

real    0m11.306s
user    0m10.117s
sys     0m1.188s

しかし、これは部分的にBashが遅いからです。標準のshバージョンは、Dashを使用してより速く実行されます。

$ time dash foo2.sh bar < file
bar

real    0m3.467s
user    0m2.113s
sys     0m1.353s

しかし、まだ格差がある。3倍のスケール。スクリプトはほとんど瞬間的ではなく数秒かかりますgrep。このファイルはまだ100万行にすぎず、サイズは約4MBです。問題を見ることを願っています。

関連情報