実行時に提供された数値に基づいて複数のパターンを一致させるためにgrepとコマンドを設定する方法は?

実行時に提供された数値に基づいて複数のパターンを一致させるためにgrepとコマンドを設定する方法は?

少し輸出しました。マイクロソフトワード文書をプレーンテキストに変換し、この関数を使用して.txt現在のディレクトリにあるファイルの内容を解析します。

mo1 () {
for i in *.txt; do
    echo "File: $i"
    grep -n -HC 1 "$@" "$i"
done
}

検索するパターンが複数ある場合は、これを行うことができますmo1 | grep pattern2。しかし、grep -E 'pattern1.*pattern2[.*...]...'実行時に関数に提供されるパターンの数(など)によって結果が異なるタスクを実行するにはmo1 pattern1 pattern2 [...]どうすればよいですか。配列が項目数を提供できることがわかり、@ループ(finalpattern = '$ 1. * $ 2. * $ 3')を介して変数を設定できます。これは最終的に使用される式になりますgrep。しかし、関数で式を作成する部分を抽象化する方法がわかりませんか?それとも、このようなことを行うより良いより簡単な方法はありますか?

ベストアンサー1

printf内蔵機能を活用できます。

mo1 () {
  for file in *.txt; do
    grep -n -C1 "$(printf "%s.*" "$@")" "$file"
  done
}

この単純なバージョンは.*最後の要素の後に挿入されます。この特定のユースケースでは重要ではありませんが、他の場合(たとえばgrep -o.*

mo1 () {
  pattern=$(printf "%s.*" "$@")
  pattern=${pattern%??}
  for file in *.txt; do
    grep -n -C1 "$pattern" "$file"
  done
}

Bashでは、printf出力を変数に直接置くことができますが、これはコマンド置換を使用するよりも少し高速です(ただし、サブシェルが遅いCygwinでも問題ではありません)。

mo1 () {
  printf -v pattern "%s.*" "$@"
  pattern=${pattern%??}
  for file in *.txt; do
    grep -n -C1 "$pattern" "$file"
  done
}

位置パラメータ間に単一の文字を挿入するには、IFSその文字を設定してを使用します"$@"。ただし、この方法は区切り文字が2文字以上の場合は機能しません。 ksh、bashではパターンに現れない文字がある場合、それを利用して結合した後に置換を行うことができます。たとえば、ここではパターンに改行文字を含めることは意味がありません。

mo1 () {
  typeset IFS=$'\n'
  typeset pattern="$*"
  pattern=${pattern//$'\n'/.*}
  for file in *.txt; do
    grep -n -C1 "$pattern" "$file"
  done
}

zshにはもちろん直接的な方法があります。

mo1 () {
  for file in *.txt; do
    grep -n -C1 ${(j:.*:)@} $file
  done
}

おすすめ記事