拡張機能でbashで最後のコマンドを表示する方法

拡張機能でbashで最後のコマンドを表示する方法

このような機能を使用しています。

$ find-grep () { find . -type f -name "$1" -print0 | xargs -0 grep "$2" ; }

入力後:

$ find-grep *.c foo

最後のコマンド文字列を拡張したいと思います。この場合:

find . -type f -name "*.c" -print0 | xargs -0 grep "foo"

簡単にできる方法はありますか?

答え1

@slmのより健全なバージョン:

find-grep() {
  cmd=(find . -type f -name "$1" -exec grep "$2" {})
  printf '%q ' "${cmd[@]}"
  printf '+\n'
  "${cmd[@]}" +
}

(パイプやxargsここでは必要ありません)または:

find-grep () (
  set -x
  find . -type f -name "$1" -exec grep "$2" {} +
)

(範囲を制限するためにサブシェルを起動する()のではなく、注意してください。より多くのプロセスが分岐せず、実行されるプロセスがより早く完了することに注意してください。){}set -xforkfind

シェルがワイルドカード文字を拡張しないようにワイルドカード文字を引用する必要があることに注意してください。

find-grep '*.c' pattern

Up代わりに、キーを押したときに拡張コマンドが表示されるように履歴にプッシュするには、次のように書くことができます。

find-grep() {
  cmd=$(printf '%q ' find . -type f -name "$1" -exec grep "$2" {})+
  history -s "$cmd"
  eval "$cmd"
}

答え2

1つの方法は次のとおりです。

$ find-grep () {
  cmd=(find . -type f -name \"$1\" -print0 \| xargs -0 grep \"$2\")
  printf "%s\n" "${cmd[*]}" 
  eval "${cmd[*]}"
}

はい

以下は、いくつかのサンプルデータです。

$ ls -l
total 8
-rw-rw-r-- 1 saml saml 4 Sep 21 10:44 1.c
-rw-rw-r-- 1 saml saml 4 Sep 21 10:44 2.c
-rw-rw-r-- 1 saml saml 0 Sep 21 10:22 3.c
-rw-rw-r-- 1 saml saml 0 Sep 21 10:22 4.c
-rw-rw-r-- 1 saml saml 0 Sep 21 10:22 5.c

これは、2つのファイルに「foo」という文字列を含む関数の実際の実行です。

$ find-grep '*.c' "foo"
find . -type f -name "*.c" -print0 | xargs -0 grep "foo"
./2.c:foo
./1.c:foo

説明する

この特定のバージョンの関数は、次のように異なります。

  1. 私たちはあなたのコマンドで変数を定義します$cmd=(find....)。コマンドは配列にラップされます(..)
  2. $cmd我々はエコー生成配列を使用しますprintf。配列が個々の要素のリストではなく単一の文字列として検索されるように、シンボルを使用して*配列要素を渡します。${cmd[*]}
  3. 最後に、配列を評価して$cmd実行します。

別の方法

次のように関数をラップすることもできます。set -x ...function... set +xこれは期間中だけデバッグをオンにしてオフに...function...する効果があります。

$ find-grep () { 
  set -x
  find . -type f -name "$1" -print0 | xargs -0 grep "$2"
  set +x
}

はい

$ find-grep *.c foo
+ find . -type f -name '*.c' -print0
+ xargs -0 grep foo
+ set +x

この方法は読みやすくはありませんが、パフォーマンスに基づいて分類され、同じ全体的な機能を示します。最初はそうで、find ...次はそうでしたxargs ...

関連情報