0

~/.bash_profile に次のフィルターを関数として記述しました。

hilite() {
 export REGEX_SED=$(echo $1 | sed "s/[|()]/\\\&/g")
 while read line
 do
  echo $line | egrep "$1" | sed "s/$REGEX_SED/\x1b[7m&\x1b[0m/g"
 done
 exit 0
}

正規表現に一致するパイプされた行を検索し、VT100 互換端末で ANSI エスケープ コードを使用して一致を強調表示します。

たとえば、次の例では、/etc/passwd の最後の 10 行の単語全体である文字列binUまたは1を検索して強調表示します。

tail /etc/passwd | hilite "\b(bin|[U1])\b"

ただし、各行が echo、egrep、および sed をフォークするため、スクリプトの実行は非常に遅くなります。

この場合、入力全体に対して egrep を実行し、その出力に対して sed を実行する方が効率的です。

これを行うために関数を変更するにはどうすればよいですか? 可能であれば、一時ファイルを作成しないことをお勧めします。

PS 同様の方法で行を見つけて強調表示する別の方法はありますか?

4

5 に答える 5

2

egrepサポートしている場合は--color、これを.bash_profileに入れてください。

  hilite() { command egrep --color=auto "$@"; }

(個人的には、関数に名前を付けますegrep。したがって、の使用法ですcommand)。

于 2012-10-31T15:10:48.713 に答える
2

whileループ全体を単純に置き換えることができると思います

sed -n "s/$REGEX_SED/\x1b[7m&\x1b[0m/gp"

標準入力から行ごとに読み取ることsedができるため、必要ありませんread

実行egrepしてパイプする方が単独でsed使用するよりも速いかどうかはわかりませんsedが、 を使用していつでも比較できますtime

編集:ハイライトされた行のみを印刷するために-npを追加しました。sed

于 2012-10-31T14:34:57.237 に答える
2

sed-nフラグ (またはスクリプト内の命令)を与えると、#n要求されない限り出力をエコーし​​ません。そう

while read line
 do
  echo $line | egrep "$1" | sed "s/$REGEX_SED/\x1b[7m&\x1b[0m/g"
 done

に簡略化できます

sed -n "s/$REGEX_SED/\x1b[7m&\x1b[0m/gp"

編集:これが関数全体です:

hilite() { 
    REGEX_SED=$(echo $1 | sed "s/[|()]/\\\&/g");
    sed -n "s/$REGEX_SED/\x1b[7m&\x1b[0m/gp"
}

これですべてです。while ループ、読み取り、grep などはありません。

于 2012-10-31T19:10:03.983 に答える
1

さて、あなたは単にこれを行うことができます:

egrep "$1" $line | sed "s/$REGEX_SED/\x1b[7m&\x1b[0m/g"

しかし、それがはるかに速くなるかどうかはわかりません; )。

于 2012-10-31T12:28:56.140 に答える
0

念のため、これは一時ファイルを使用する方法です。

hilite() {
 export REGEX_SED=$(echo $1 | sed "s/[|()]/\\\&/g")
 export FILE=$2
 if [ -z "$FILE" ]
 then
  export FILE=~/tmp
  echo -n > $FILE
  while read line
  do
   echo $line >> $FILE
  done
 fi
 egrep "$1" $FILE | sed "s/$REGEX_SED/\x1b[7m&\x1b[0m/g"
 return $?
}

また、次のような場合に、ファイル/パス名を 2 番目の引数として取ります。

cat /etc/passwd | hilite "\b(bin|[U1])\b"
于 2012-11-01T20:05:46.877 に答える