Grepエイリアス-パイプラインにない限り行番号


25

行番号を追加するgrepのbashエイリアスを作成したい:

alias grep='grep -n'

しかし、それはもちろん、パイプラインにも行番号を追加します。ほとんどの場合(例外もありません)、パイプライン内に行番号は必要ありません(少なくとも内部的には、おそらく最後であればOKです)。また、sed / awk / cutをそれらを取り出すためのパイプライン。

おそらく私の要件は、「grepが行の唯一のコマンドである場合にのみ行番号を追加する」ように簡略化できます。特にいエイリアスなしでこれを行う方法はありますか?

回答:


27

次のような関数をbash(またはPOSIXシェル)で使用できます。

grep() { 
    if [ -t 1 ] && [ -t 0 ]; then 
        command grep -n "$@"
    else 
        command grep "$@"
    fi
}

[ -t 1 ]一部が使用[コマンド(としても知られるtest STDOUTがTTYに関連付けられているかどうかをチェックします。

[ -t 0 ]あなたがいる場合のみ、行番号を追加するために、指定するのでチェックし、標準入力だけでなく、grepある唯一のパイプラインでコマンド。


5
また[[ -t 0 && -t 1 ]]、標準入力と標準出力の両方が端末に接続されている場合にのみ行番号が必要な場合は、テストを行います。
ジル「SO-悪であるのをやめる」

3

(完全を期すため)

一方で、@のenzotibの答えはおそらくあなたが望むものである、それはあなたが何を求めていないのです。[ -t 1 ]ファイル記述子が端末デバイスであるかどうかをチェックします。パイプ以外のもの(通常のファイル、ソケット、その他のタイプのデバイスなど/dev/null)ではありません

この[コマンドには-t、パイプ以外のものはありません。ファイル記述子に関連付けられているファイルの種類を取得するには、そのファイルに対してfstat()システムコールを実行する必要があります。それを行うための標準コマンドはありませんが、一部のシステムまたはシェルにはいくつかあります。

GNUの場合stat

grep() {
  if { [ "$(LC_ALL=C stat -c %F - <&3)" = fifo ]; } 3>&1 ||
     [ "$(LC_ALL=C stat -c %F -)" = fifo ]; then
    command grep "$@"
  else
    command grep -n "$@"
  fi
}

またはzsh、独自のstatビルトイン(数年前にGNUの1つより前のもの)を使用して、ここでzstatのみロードされます:

grep() {
  zmodload -F zsh/stat b:zstat
  local stdin_type stdout_type
  if zstat -A stdin_type -s -f 0 +mode &&
     zstat -A stdout_type -s -f 1 +mode &&
     [[ $stdin_type = p* || $stdout_type = p* ]]
  then
     command grep "$@"
  else
     command grep -n "$@"
  fi
}

次に、いくつかのメモ:

パイプを使用するのはシェルパイプラインだけではありません。

var=$(grep foo bar)

または:

cmd <(grep foo bar)

または:

coproc grep foo bar

またgrep、stdoutをパイプに接続して実行します。

シェルがの場合、ksh93一部のシステムでは、パイプラインでパイプの代わりにソケットペアを使用することに注意してください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.